操作系统折腾记(三)
wait
https://www.ibm.com/docs/en/ztpf/2020?topic=apis-waitwait-status-information-from-child-process
1 | |
等待任一子进程退出,如果正常获取到了子进程的退出信息(存入 stat_loc 指向的地址),返回该子进程的 pid;否则立即返回 -1 并设置 errno(据实践,不会更改 *stat_loc 原本的值,「立即返回」应该就是这个意思)。
注意,wait 的返回值只说明了它本身有没有被正常地执行,并不能说明子进程是怎样退出的。无论子进程是怎么挂掉的,只要 wait 成功地搞到了子进程挂掉的信息(stat_loc),就返回 pid (>0);什么时候搞不到呢,一是调用 wait 的进程本来就没有子进程,二是 wait 被信号中断了。
那么子进程有哪些退出状态呢?CSAPP 中说到,进程会因为三种原因终止:
- 收到一个信号
- 从主程序返回
- 调用
exit函数:有一个 exit code,如exit(0)、exit(-1)
那我们怎么知道子进程是因为什么原因而退出的呢?看 stat_loc 呗!怎么个看法呢?见下文 WIFEXITED & WEXITSTATUS 一节。
waitpid
https://www.ibm.com/docs/en/ztpf/2020?topic=apis-waitpidobtain-status-information-from-child-process
1 | |
类似于 wait,但功能更强大了。首先,pid 参数有以下两种选择:
pid>0:等待集合就是 ID 为pid的子进程pid=-1:等待集合是所有 子进程
其次,options 选项提供了 waitpid 行为的选择:
- 默认为
0,则waitpid会挂起调用它的进程,直到等待集合中的某一个子进程终止;当然,如果本来就有终止的子进程,那么就立即返回了 WNOHANG:如果等待集合中没有已经终止的子进程,就立即返回而不挂起等待- ……
WIFEXITED & WEXITSTATUS
https://www.ibm.com/docs/en/ztpf/2020?topic=zca-wifexitedquery-status-see-if-child-process-ended-normally
https://www.ibm.com/docs/en/ztpf/2020?topic=apis-wexitstatusobtain-exit-status-child-process
https://www.ibm.com/docs/en/ztpf/2020?topic=zca-wifsignaledquery-status-see-if-child-process-ended-abnormally
https://www.ibm.com/docs/en/ztpf/2020?topic=zca-wtermsig-determine-which-signal-caused-child-process-exit#cpp_wtermsig
https://blog.csdn.net/duyuguihua/article/details/38986197
https://blog.csdn.net/y396397735/article/details/53769865
https://stackoverflow.com/questions/47441871/why-should-we-check-wifexited-after-wait-in-order-to-kill-child-processes-in-lin
1 | |
我们知道,父进程调用 wait 或者 waitpid 时需要传入一个 &status,意即获取子进程的退出状态。大多数情况下,我们并不关心子进程怎么挂掉的,所以经常这么写:wait(NULL) 或者 wait(0)。
但有的时候我们就是想看看 status。status 能指出子进程是怎样退出的、如果是 exit 的话返回值是啥、如果是被信号结束的话是被谁结束的……这些信息被编码进了一个 int 的二进制位中。但是每次找某个二进制位也太麻烦了吧,所以为了方便,人们定义了一套宏,用来解析 status 的信息:
WIFEXITED(status)如果子进程是调用 exit 退出的,返回 TRUE,接下来我们需要用
WEXITSTATUS获取子进程的 exit code;否则返回 FALSE。WEXITSTATUS(status)返回子进程的 exit code,当然前提是
WIFEXITED(status)是 TRUE,否则返回值没有任何意义。WIFSIGNALED(status)如果子进程是因为信号而退出的,返回 TRUE,接下来我们需要用
WTERMSIG获取究竟是什么信号让它退出的;否则返回 FALSE。WTERMSIG(status)返回让子进程退出的信号对应的数值(什么信号对应什么数值在
sys/signal.h中有定义),前提是WIFSIGNALED(status)是 TRUE,否则返回值没有任何意义。……
(注:C 语言没有 bool 类型,也没有 true 和 false,上文中的 TRUE 泛指非零值,FALSE 指 0 值)