操作系统折腾记(三)
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 值)