1、说下你知道的Linux命令
列出文件列表:ls 【参数 -a -l】
创建目录和移除目录:mkdir rmdir
用于显示文件后几行内容:tail
打包:tar -xvf
打包并压缩:tar -zcvf
查找字符串:grep
显示当前所在目录:pwd
创建空文件:touch
编辑器:vim vi
执行以下命令将会重新启动系统: reboot
以下命令将在10分钟之后重新启动系统: shutdown -r +10
mv指令 需要移动的文档路径 需要保存的位置路径
rm指令 rm指令 -f:force,强制删除,不提示是否删除 -r:表示递归
Linux常用指令(命令)超级无敌全合集加图文说明_linux命令-CSDN博客
2、linux下,指定文件file1为所有用户可读,可写,可执行,执行命令:___1__。修改file1的拥有者为test,拥有组为user,执行命令:___2__。
chmod 777 file1,chown test file1 , chgrp user file1
3、
4、在Linux环境下,用Linux基本命令完成如下操作:
1、重命名/home/qqbook/script/下的aa.txt 文件名为:cc.txt ;
mv /home/qqbook/script/aa.txt /home/qqbook/script/cc.txt
2、清空/home/qqbook/script目录下的所有内容。
rm -rf /home/qqbook/script/*
5、Linux系统下,用什么命令来查看系统进程? ps
6、在Linux环境下,用Linux基本命令完成如下操作:
1、切换到/home/qqbook/script目录下 ;
cd /home/qqbook/script
2、在该目录下,查找包含有“feidu”文本内容的所有文件名。
grep -rl "feidu" .
-r
选项表示递归地搜索子目录中的文件;-l
选项表示只输出包含匹配文本的文件名,而不显示具体匹配行的内容;- "feidu"是要查找的文本内容;
- "."表示当前目录。
7、静态库和动态库的区别
linux下有两种库:动态库和静态库 (共享库) 二者的不同点在于代码被载入的时刻不同。. 静态库的代码在编译过程中已经被载入可执行程序,因此体积比较大。. 动态库 (共享库)的代码在可执行程序运行时才载入内存,在编译过程中仅简单的引用,因此代码体积比较小。. 不同的应用程序如果调用相同的库,那么在内存中只需要有一份该动态库 (共享库)的实例。. 静态库和动态库的最大区别,静态情况下,把库直接加载到程序中,而动态库链接的时候,它只是保留接口,将动态库与程序代码独立,这样就可以提高代码的可复用度,和降低程序的耦合度。. 静态库在程序编译时会被连接到目标代码中, 程序运行时将不再需要该静态库 。
在Linux环境下,您可以使用以下命令来创建静态库和动态库:
- 创建静态库:
ar rc libabc.a file1.o file2.o file3.o
其中libabc.a
是要创建的静态库名,file1.o
、file2.o
和file3.o
是要包含在静态库中的目标代码文件(通常是由C语言编写的)。
运行上述命令后,将会创建一个名为libabc.a
的静态库,包含了file1.o、file2.o和file3.o文件中的目标代码。您可以在编译时使用该静态库来链接到您的程序中。
- 创建动态库:
gcc -fPIC -shared -o libabc.so file1.c file2.c file3.c
其中libabc.so
是要创建的动态库名,file1.c
、file2.c
和file3.c
是要包含在动态库中的源代码文件(通常是由C语言编写的)。
运行上述命令后,将会创建一个名为libabc.so
的动态库,包含了file1.c、file2.c和file3.c文件中的编译后的目标代码。您可以在运行时使用该动态库来链接到您的程序中。
请注意,动态库需要在运行时才能够链接到程序中,因此在编译时需要将其链接到程序中;而静态库则需要在编译时就链接到程序中。另外,动态库的大小通常比静态库小,并且可以被多个程序共享,因此在实际开发中通常更加常用。
8、多线程程序不易维护的原因主要有以下几个方面:
-
竞态条件(Race Condition):在多线程环境下,多个线程同时访问和修改共享数据时可能导致竞态条件的出现。这意味着程序的执行结果依赖于不同线程之间的执行顺序,而这种顺序是不确定的。调试和修复竞态条件问题非常困难,因为问题可能只在特定的条件下才会出现。
-
死锁(Deadlock):当多个线程相互等待对方释放资源时,可能会导致死锁。死锁是一种无法继续执行的状态,需要手动解除。诊断和解决死锁问题需要深入了解线程之间的依赖关系和资源使用情况。
-
上下文切换开销:多线程程序在切换线程时需要保存和恢复线程的上下文,这会引入一定的开销。如果线程数过多,频繁的上下文切换会占用大量的系统资源,降低程序的性能。
-
难以追踪和调试:多线程程序中存在多个并发执行的执行路径,线程之间的交互关系复杂,这使得程序的行为难以追踪和调试。当出现问题时,需要分析多个线程的执行状态和相互之间的影响,增加了调试的难度。
为减轻多线程程序的维护难度,可以采取以下的策略:
-
设计良好的线程同步机制:合理设计和使用锁、信号量、条件变量等同步机制,确保共享资源的正确访问和修改顺序,避免竞态条件和死锁的发生。
-
减少共享数据的使用:尽量避免多个线程直接共享数据,可以通过消息传递、函数参数等方式减少全局共享数据的使用。减少共享数据可以降低竞态条件的风险。
-
使用线程安全的数据结构和库:选择使用已经经过线程安全测试和验证的数据结构和库,减少自行实现线程安全的工作量和风险。
-
控制线程数量:合理控制并发线程的数量,避免创建过多的线程导致上下文切换开销过大。
-
使用工具和技术:借助调试工具、性能分析工具和代码审查等方法来辅助追踪和调试多线程程序,以提高效率和准确性。
尽管多线程程序具有一定的挑战性,但如果能够合理使用和管理多线程,它们可以显著提高程序的性能和响应能力。
9、什么是线程池
线程池(Thread Pool)是一种用于管理和复用线程的机制。它通过预先创建一定数量的线程,并将它们组织在一个池中,以便在需要时重复利用这些线程,而不需要频繁地创建和销毁线程。
10、 创建文件时使用 open函数
关闭一个文件 close函数
把指定数目的数据写到文件 write函数
删除文件 remove库函数
进程号为0及1的进程由内核创建。
进程号为0的进程通常是调度进程,常被称为交换进程(swapper)。进程号为1的进程通常是init进程。
除调度进程外,在linux下面所有的进程都由进程init进程直接或者间接创建。
fork创建子进程,子进程复制父进程资源,父子进程谁先执行受限于进程调度。
进程在一定的时间内没有任何动作,称为进程的挂起 unsigned int sleep(unsigned int sec);
进程资源的回收 1、 pid_t wait(int *status); 函数返回时,参数status中包含子进程退出时的状态信息
返回值:如果执行成功则返回子进程的进程号。出错返回-1,失败原因存于errno中。
2、pid_t waitpid(pid_t pid, int *status,int options)
pid>0:
等待进程ID等于pid的子进程。
pid=0
等待同一个进程组中的任何子进程,如果子进程已经加入了别的进程组,waitpid不会等待它。
pid=-1:
等待任一子进程,此时waitpid和wait作用一样。
pid<-1:
等待指定进程组中的任何子进程,这个进程组的ID等于pid的绝对值。
status参数中包含子进程退出时的状态信息。
options参数能进一步控制waitpid的操作:
0:
同wait,阻塞父进程,等待子进程退出。
WNOHANG:
没有任何已经结束的子进程,则立即返回。
WUNTRACED
如果子进程暂停了则此函数马上返回,并且不予以理会子进程的结束状态。(跟踪调试,很少用到)
3、VFork创建进程
vfork和fork的区别:
vfork保证子进程先运行,在它调用exec或exit之后,父进程才可能被调度运行。
父子进程有各自独立的栈区
vfork和fork一样都创建一个子进程,但它并不将父进程的地址空间完全复制到子进程中,因为子进程会立即调用exec(或exit),于是也就不访问该地址空间。
相反,在子进程中调用exec或exit之前,它在父进程的地址空间中运行,在exec之后子进程会有自己的进程空间
4、守护进程
1、创建一个进程,父进程必须退出,形式脱离了终端(必须)
2、创建一个会话,真正意义上脱离终端(必须) pid_t setsid(void);
3、改变目录 (根目录)——可选
4、文件掩码——可选
5、关闭文件描述符
5、创建无名管道函数 int pipe(int filedes[2]); 功能:经由参数filedes返回两个文件描述符
6、重定向函数 int dup(int fildes); int dup2(int fildes, int fildes2);
7、创建有名管道的函数 int mkfifo(const char *pathname, mode_t mode);
8、与无名管道、命名管道一样,从消息队列中读出消息,消息队列中对应的数据都会被删除。
9、创建消息队列的API
1、创建键值 key_t ftok(const char *pathname, int proj_id);
2、创建消息队列 int msgget(key_t key, int msgflg);
3、消息结构体
typedef struct _msg
{
long mtype; /*消息类型*/
char mtext[100]; /*消息正文*/
... /*消息的正文可以有多个成员*/
}MSG;
4、发送消息 int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
5、接收消息 ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);
10、共享内存的API
1、获得一个共享存储标识符 int shmget(key_t key, size_t size,int shmflg);
11、
中断的分类
1、硬件中断:除数为0,无效的内存访问等。这些情况通常由硬件检测到,并通知内核,然后内核产生适当的信号发送给相应的进程。
软件中断:当检测到某种软件条件已发生,并将其通知有关进程时,产生信号。
2、注册信号处理函数(不可用于SIGKILL、SIGSTOP信号),即确定收到信号后处理函数的入口地址。
void (*signal(int sig, void (*func)(int)))(int); 自定义信号处理函数:信号处理函数名
12、1、创建线程
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);
2、回收线程资源 int pthread_join(pthread_t thread, void **retval);
retval:用来存储线程退出状态的指针的地址。
3、线程分离 int pthread_detach(pthread_t thread);
使调用线程与当前进程分离,使其成为一个独立的线程,该线程终止时,系统将自动回收它的资源。