文章结构:
wait能力介绍
在上一篇【C/C++】多进程:子进程的创建fork()中演示了子进程的创建。
创建子进程后,父进程具有监听子进程的运行状态的能力,用到的函数为:
#include <sys/wait.h>
pid_t wait(int *status);
pid_t waitpid(pid_t pid, int *status, int options);
以上函数用于等待子进程子进程的状态变化回调并且获取状态变化信息。所能获取到的状态变化包括:子进程运行结束、子进程被信号量暂停、子进程被信号量恢复运行。
父进程执行了wait
函数后,如果子进程已经发生了状态变化,则wait
函数立即就会有返回结果;否则wait
函数会一直阻塞直至子进程状态发生变化。
通常意义上,如果子进程已经发生了状态变化,但还未被父进程或其它系统回调执行wait
,则把此时的子进程称为是可等待的(waitable)。
子进程运行结束后,父进行执行wait
函数可以推动系统释放与子进程相关的资源;否则子进程将会被维持在僵尸进程
的状态下一直存在。
wait()函数讲解
函数wait(int * status)
是对waitpid()
的封装,限定了只有在任一子进程运行结束时才会有返回,否则调用进程会一起处于阻塞状态暂停执行。wait(int * status)
等同于如下代码:
waitpid(-1, &status, 0);
waitpid()
会阻塞调用进程直至任一子进程的运行状态发生变化。接下来对waitpid()
的三个参数进行讲解:
- pid
pid < -1
取该pid的绝对值,如果任意子进程的进程组ID等于该绝对值,则该组进程中任一子进程中的进程状态发生变化都会触发waitpid()
的回调。
pid == -1
监听范围扩大到任意子进程。
pid == 0
监听限制为子进程的进程组ID与父进程相等。
pid > 0
监听限制为指定子进程进程ID值。
- status
值可以为NULL
。当不为NULL
时,用于存储触发状态变化的信息号值和exit(code)
中的code
值。
wait.h
头文件定义了几个宏用于解析status
的值,常见的有:
宏 | 含义 |
---|---|
WIFEXITED(status) WEXITSTATUS(status) |
当子进程调用exit(code) 或_exit(code) 或正常运行到main() 函数结尾时正常结束运行,则返回true 。当 WIFEXITED(status) 为true 时,获取exit(code) 或_exit(code) 的code 值。其中 code 只能为0或正数,不支持负数。 |
WIFSIGNALED(status) WTERMSIG(status) |
当子进程被信号量杀死时则返回true 。当 WIFSIGNALED(status) 为true 时,获取该信号量的值。 |
WIFSTOPPED(status) WSTOPSIG(status) |
当子进程被信号量暂停执行时则返回true 。当 WIFSTOPPED(status) 为true 时,获取该信号量的值。 |
- options
值可以是以下常量的任意值或任意常量与0的OR
计算值。
常量 | 含义 |
---|---|
WNOHANG | 调用wait 时指定的pid 仍未结束运行,则wait 立即返回0。 |
WUNTRACED | 当子进程被暂停时,则wait 立即返回子进程的pid 。 |
WCONTINUED |
当被暂停的子进程又被信号量恢复后,则wait 立即返回子进程的pid 。Linux 2.6.10及以后生效。在Mac 0S X 10.9.5上未生效。 |