一. 概念
1. 并行与并发:区分的关键点是“同时”。
并行(parallel):指在同一时刻,有多条指令在多个处理器上同时执行。
并发(concurrency):指在同一时刻只能有一条指令执行,但多个进程指令被快速的轮换执行,使得在宏观上具有多个进程同时执行的效果。即宏观上同时,微观上交替执行。
2. 进程控制块PCB
进程运行时,内核为每个进程分配一个PCB(进程控制块),维护进程相关的信息,Linux内核的进程控制块是task_struct结构体。 查看struct task_struct 结构体定义: vim /usr/src/linux-headers-4.10.0-28/include/linux/sched.h
3. 文件描述符表:包含很多指向file结构体的指针,就在进程控制块的task_struct结构体中。
二. 进程
1. 进程相关shell命令:
ps -aux:进程状态。
top:动态显示进程状态。
kill:指定进程号杀死进程。
killall:指定进程名杀死进程。
./a.out &:查看当前进程号。
pid:n(进程号):查看指定进程的父进程号。
2. 进程相关函数:
#include <sys/types.h>
#include <unistd.h>
pid_t getpid(void); //获取本进程号
pid_t getppid(void); //获取调用此函数的父进程号
pid_t getpgid(pid_t pid); //获取进程组号
pid_t fork(void); //创建子进程
进程创建函数还是值得一提的,根据返回值判断父子进程:返回0表示子进程,返回-1表示失败,返回其他值就是父进程,这个值表示子进程ID,因为父进程是没有函数可以获取到子进程ID的。
fork函数失败的两种情况:
1. 进程数到达系统上线,error设置为EAGAIN。
2. 系统内存不足,error设置为ENOMEM
3. 等待子进程退出相关函数:
每个进程在退出的时候,内核释放该进程的所有资源,包括打开的文件、占用的内存等。但是依然为其保留一定的信息。,这些信息主要值进程控制块PCB的信息(包括进程号、退出状态、运行时间等)。
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *status);
pid_t waitpid(pid_t pid, int *status, int options);
功能:
等待任意一个子进程结束,如果任意一个子进程结束了,此函数会回收该子进程的资源。
参数:
status : 进程退出时的状态信息。
宏函数可分为如下三组:
1) 正常退出
WIFEXITED(status) 为非0 → 进程正常结束。
WEXITSTATUS(status) 如上宏为真,使用此宏 → 获取进程退出状态 (exit的参数)。
2) 异常终止
WIFSIGNALED(status) 为非0 → 进程异常终止。
WTERMSIG(status) 如上宏为真,使用此宏 → 取得使进程终止的那个信号的编号。
3) 暂停状态
WIFSTOPPED(status) 为非0 → 进程处于暂停状态。
WSTOPSIG(status) 如上宏为真,使用此宏 → 取得使进程暂停的那个信号的编号。
WIFCONTINUED(status) 为真 → 进程暂停后已经继续运行。
waitid函数:
#include <sys/types.h>
#include <sys/wait.h>pid_t waitpid(pid_t pid, int *status, int options);
功能:
等待子进程终止,如果子进程终止了,此函数会回收子进程的资源。参数:
pid : 参数 pid 的值有以下几种类型:
pid > 0 等待进程 ID 等于 pid 的子进程。
pid = 0 等待同一个进程组中的任何子进程,如果子进程已经加入了别的进程组,waitpid 不会等待它。
pid = -1 等待任一子进程,此时 waitpid 和 wait 作用一样。
pid < -1 等待指定进程组中的任何子进程,这个进程组的 ID 等于 pid 的绝对值。status : 进程退出时的状态信息。和 wait() 用法一样。
options : options 提供了一些额外的选项来控制 waitpid()。
0:同 wait(),阻塞父进程,等待子进程退出。
WNOHANG:没有任何已经结束的子进程,则立即返回。
WUNTRACED:如果子进程暂停了则此函数马上返回,并且不予以理会子进程的结束状态。(由于涉及到一些跟踪调试方面的知识,加之极少用到)
返回值:
waitpid() 的返回值比 wait() 稍微复杂一些,一共有 3 种情况:
1) 当正常返回的时候,waitpid() 返回收集到的已经回收子进程的进程号;
2) 如果设置了选项 WNOHANG,而调用中 waitpid() 发现没有已退出的子进程可等待,则返回 0;
3) 如果调用中出错,则返回-1,这时 errno 会被设置成相应的值以指示错误所在,如:当 pid 所对应的子进程不存在,或此进程存在,但不是调用进程的子进程,waitpid() 就会出错返回,这时 errno 被设置为 ECHILD;