函数 wait 和函数 waitpid
- 当一个进程正常或者异常终止时,内核就向其父进程发送SIGCHID信号。因为子进程终止是个异步事件(就是可以在父进程运行的任何时候发生),所以这种信号也就是内核向父进程发的异步通知。父进程可以选择忽略该信号,或者提供一个该信号发生时即被调用执行的函数(信号处理程序)。对于这种信号的系统默认动作是忽略它。
- 需要知道的是调用wait或waitpid的进程可能会发生什么?
如果其所有子进程都还在运行,则阻塞。
如果一个子进程已终止,正等待父进程获取其终止状态,则取得该子进程的终止状态立即返回。
如果它没有任何子进程,则立即出错返回。 - 如果进程由于接收到SIGCHLD信号而调用wait,我们期待wait会立即返回。但是如果在随机时间点调用wait,则进程可能会阻塞。
#include<sys/wait.h>
pid_t wait(int* statloc);
pid_t waitpid(pid_t pid, int* statloc, int options);
//两个函数返回值:若成功,返回进程ID;若出错,返回0或者-1
这两个函数的区别如下:
-
在一个子进程终止前,wait 使其调用者阻塞,而waitpid 有一个选项,可使调用不阻塞。
-
waitpid 并不等待在其调用之后的第一个终止子进程,它有若干个选项,可以控制它所等待的进程。
-
如果子进程已经终止,并且是一个僵尸进程,则wait 立即返回并取得该子进程的状态;否则wait 使其调用阻塞,直到一个子进程终止。如调用者阻塞而且它有多个子进程,则在其某一子进程终止时,wait就立即返回。因为wait 返回终止子进程的进程ID,所以它总能了解是哪一个子进程终止了。
-
这两个函数的参数statloc 是一个整形指针。如果statloc 不是一个空指针,则终止进程的终止状态就存在它所指向的单元内。如果不关心终止状态,则可将该参数指定为空指针。
-
对于waitpid 函数中pid 参数的作用解释如下:
- pid == -1 等待任一子进程。此种情况下,waitpid 与 wait 等效。
- pid > 0 等待进程ID与pid 相等的子进程。
- pid == 0 等待组ID等于调用进程组ID的任一子进程(后面介绍进程组)
- pid < -1 等待组ID等于pid 绝对值的任一子进程
-
waitpid 函数返回终止子进程的进程ID,并将该子进程的终止状态存放在由statloc 指向的存储单元内。对于wait,其唯一的出错就是调用进程没有子进程(函数调用被一个信号中断时,也可能返回另一种出错,后面再说)。但是对于waitpid,如果指定的进程或进程组不存在,或者参数pid指定的进程不是调用进程的子进程,都可能出错。
-
waitpid 函数提供了wait 函数没有提供的3个功能。
(1). waitpid 可等待一个特定的进程,而wait则返回任一终止子进程的状态。
(2). waitpid 提供了一个wait 的非阻塞版本有时希望获取一个子进程的状态,但不想阻塞。
(3). waitpid 通过WUNTRACED和WCONTINUED选项支持作业控制。
有关僵死进程的讨论
如果一个进程fork 一个子进程,但不要它等待子进程终止,也不希望子进程处于僵死状态直到父进程终止,实现这一个要求的诀窍是调用fork两次。