1. 进程的定义:进程是程序(有一定独立功能)的一次运行活动,即一个程序运行就产生了一个进程;
2. 进程与程序的区别
进程 | 程序 | |
存在状态 | 动态的 | 静态的 |
生命周期 | 暂时的 | 长久的 |
组成 | 由程序、数据、控制快组成 | 程序代码 |
对应关系 | 一个进程可以包括多个程序 | 一个程序执行多,可以对应多个进程 |
3. 进程的生命周期阶段
①创建:父进程创建子进程,可逐级创建;init是初始化进程,是所有用户进程的父进程;
②运行:可以利用以下命令在Linux终端下查询进程:
ps -ef //罗列当前的进程、进程id |
ps axu //查询显示所有进程的状态; |
③撤销:释放进程所占空间;退出CPU使用队列;但是无法删除进程id;但是可以改变进程状态;
4. 僵尸进程与孤儿进程
僵尸进程:父进程没有删除已经撤销的进程,导致该进程占着空间不干事;
孤儿进程:父进程先结束,子进程就成了孤儿进程,该子进程就会传递给init进程,称为新的父进程;
5. 进程经典三态
①执行状态:进程正在占用CPU;
②就绪状态:进程已具备一切条件,正在等待分派CPU的处理时间片;
③等待状态:进程不能使用CPU,条件满足后使用CPU;
6. Linux进程之间的关系是并行性,互不干扰等特点,每个进程都有独立的运行空间,用于各自的功能;一个进程发生异常,不会影响其他进程;
7. Linux中的进程分为3个段:
①数据段:存放全局变量,常数以及动态数据分配的数据空间;
②代码段:存放的是程序代码的数据;
③堆栈段:存放的是子程序的返回地址、子程序的参数以及程序的局部变量;
8. 进程ID
①进程ID(PID):标识进程的唯一数字;
②父进程ID:PPID;
③启动进程的用户ID:UID;
9. 进程互斥:是指当有若干个进程都要使用某一共享资源时,任何时刻最多允许一个进程使用;
10. 临界资源、临界区:操作系统中将一次只允许一个进程访问的资源称为临界资源,进程中访问临界资源的那段程序代码称为临界区;可以锁住临界区(这段代码),这样其他进程就不会进入临界资源,用过之后就可以解锁;
11. 进程同步:一组并发进程按照一定的顺序执行的过程称为进程同步,那么具有进程同步关系的称为合作进程,合作进程之间互相发送的信号称为消息或事件;
12. 进程调度:即各进程使用CPU的规则
①抢占式:优先级高的进程打断现有进程,优先使用CPU;
②非抢占式:优先级高的不打断现有进程,等待现有进程结束后使用CPU;
进程算法:①先来先服务调度算法;
②短进程优先调度算法;
③高优先级有限算法;
④时间片轮转法;
13. 死锁:多个进程因为竞争资源而形成一种僵局,若无外力作用,这些进程都将永远不能再向前推进;
函数实现:
14. 获取进程ID
函数原型 | pid_t getpid(void); //获得本进程ID; pid_t getppid(void); //获得父进程ID; |
示例 | pid_t pid; pid = getpid(); |
参数 | 无参数 |
返回值 | 本进程或父进程ID |
头文件 | #include<sys/types.h> #include<unistd.h> |
15. 进程创建一:fork()
函数原型 | pid_t fork(void); |
示例 | pid_t id; id = fork(); |
参数 | 无参数 |
返回值 | id>0:父进程 id==0:子进程 id<0:创建失败(-1) |
头文件 | #include<sys/types.h> #include<unistd.h> |
id = fork()之前,只有一个进程在执行,但是在这条语句之后,子进程已经生成,有了独立的进程空间,那么下面的代码将同步复制到子进程中执行,且这条语句前面的变量等,也将同步复制到子进程,且变量的资值继承来时与父进程保持一致,父子进程的区别在于进程标识符(pid)不同;
可以利用id,即fork()的返回值区别父子进程,去执行不同的代码与功能;
16. 进程创建二:vfork()
函数原型 | pid_t vfork(void); |
示例 | pid_t id; id = vfork(); |
参数 | 无参数 |
返回值 | id>0:父进程 id==0:子进程 id<0:创建失败(-1) |
头文件 | #include<sys/types.h> #include<unistd.h> |
17. fork()与vfork()的区别:
fork() | vfork() | |
代码来源 | 子进程复制父进程的代码数据 | 子进程与父进程共享数据代码 |
父子进程执行次序 | 父子进程执行次序不确定,随机 | 子进程先运行,父进程后运行 |
18. 结束进程
头文件 | #include <stdlib.h> |
exit(0) | 退出程序(进程),附带清理文件缓冲区,属于库函数; |
_exit(0) | 退出程序(进程),不清理文件缓冲区,属于系统调用; |
注意return是会清理所有函数内的变量的;
19. exec函数族
函数调用:一共有6个+1个,主要分为两大类,作用是统一的:exec用被执行的程序替换调用它的程序,常用在fork创建进程后,因为fork创建一个新的进程后,产生了一个新的pid,exec启动了一个新的程序,替换原有的进程,因此新的进程pid不会改变;注意程序去执行execl调用的程序了,进程中后续的代码将不会被执行;
execl | l是指列表,即各个参数罗列出来,最后加上NULL; |
execv | v是向量,即一个数组把所有的命令行参数放到里面,最后也要加上NULL;注意是命令行参数,而不是后面程序运行后再输入的参数;如果没有 |
execl
函数原型 | int execl(const char * path, const char * arg1, ...) |
示例 | pid_t id; id = fork(); if(id == 0) { execl("./address_list_v4_sqlite3", "./address_list_v4_sqlite3", NULL); |
参数 | path:被执行的程序名(含完整路径); arg1 - - argn:被执行行程序须所需的命令行参数,含程序名,以空指针(NULL)结束; |
返回值 | 如果函数执行成功,函数无返回值; 执行失败,返回-1; |
头文件 | #include<unistd.h> |
execv
函数原型 | int execv(const char * path, char * const argv[ ]) |
示例 | pid_t id; id = fork(); if(id == 0) { char * argv[ ] = {"ls", "-al", "/etc/passwd", NULL}; execv("/bin/ls", argv); |
参数 | path:被执行的程序名(含完整路径); argv[ ]:被执行行程序所需的命令行参数数组,即把所有命令行参数放到数组中,以空指针(NULL)结束; 相当于把上面execl函数的后面所有命令行的参数都放到了数组中,包括NULL也放到里面,其他与execl无差别; |
返回值 | 如果函数执行成功,函数无返回值; 执行失败,返回-1; |
头文件 | #include<unistd.h> |
execl / execv是第一对,还有第二对、第三队大同小异,区别如下:
第二对 | execlp | 第一个参数不用含路径,其他同execl、execv; |
execvp | ||
第三对 | execle | 增加第三个参数:环境变量,char env[ ];其他同execl、execv; |
execve |
system
函数原型 | int system(const char * string) |
示例 | system("clear"); 清屏功能; |
参数 | system函数内部调用fork产生子进程,由子进程调用字符串中的命令;不同于execl那6个函数,system函数执行后依然会执行进程中后代码; 其内部机制是system调用/bin/sh-c string 去执行参数string中的命令; |
返回值 | 如果system在调用/bin/sh时失败则返回127,有其他原因失败则返回-1; |
头文件 | #include<stdlib.h> |
20. 进程等待
wait()
函数原型 | pid_t wait(int * status) |
功能 | 阻塞该进程,直到该进程的某个子进程(第一个结束的子进程)退出; |
示例 | int stat; child = wait(&stat); if(stat == 0) //表示子进程正常退出; |
参数 | status是子进程退出的状态,取地址做参数; 直接写NULL则代表,不设置状态查收,直接等到某个子进程退出; |
返回值 | 只有父进程在没有创建子进程的情况下,调用wait才会出错,返回-1; |
头文件 | #include<sys/types.h> #include<sys/wait.h> |
waitpid()
函数原型 | pid_t wait(pid_t pid, int * status, int option) |
功能 | 阻塞该进程,直到该进程的某个子进程(指定的id的进程)退出; |
参数1 | pid,有四种状态: ①pid<-1:大小等于其决定值的组内,第一个结束的子进程; ②pid==-1:找所有组内所有子进程第一个结束的子进程; ③pid==0:等待与父进程组内(与父进程平行)的第一个结束的进程; ④pid>0:指定对应id进程; |
参数2 | status是子进程退出的状态,取地址做参数; 直接写NULL则代表,不设置状态查收,直接等到某个子进程退出; |
参数3 | option,有两种方式: ①设为0:阻塞等待,那么当pid设为-1,option设为0,则等同于wait; ②WNOHANG:非阻塞等待; |
返回值 | ①-1:等待的进程不是该父进程的子进程、子进程id不存在 ②0:采用非阻塞等待; ③>0:对应结束的进程id; |
头文件 | #include<sys/types.h> #include<sys/wait.h> |