Below you will find pages that utilize the taxonomy term “Pidfd_open”
March 12, 2022
wait非子进程退出
背景
有这样一个业务场景,需要主进程可以监测它创建的子进程是否还存活,通常来说使用 waitpid 来获取子进程的状态变化情况,就可以实现需求。但是我们希望在主进程异常退出重启后还能够监测之前创建的子进程的存活情况,但是waitpid 又只能针对子进程使用。于是就有了以下问题:
- 为什么waitpid只能针对子进程使用?
- 有没有什么方法可以改变子进程的父进程?
- 有没有什么方式可以监测非子进程的退出,或者是其他状态变化?
为什么waitpid只能针对子进程使用?
wait, waitpid, waitid 这三个系统函数都是为了等待进程状态发生变化。
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *status);
pid_t waitpid(pid_t pid, int *status, int options);
int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options);
这三个系统调用都是用于等待调用进程的子进程的状态改变,并获取到子进程状态变化的相关信息。状态变化包括:子进程终止、子进程收到信号停止、子进程收到信号被唤醒。当进程退出的时候,会进程资源会被回收,但是包含进程pid、进程退出状态、资源使用信息等的一个“最小信息集”会被保留,会在进程表中占用一个位置。当父进程使用 wait 系列函数时可以获取到已经终止的子进程的最小信息集所含信息,同时这些信息被清理,占用的进程表资源被回收。如果父进程没有wait并回收掉已经终结的子进程的进程表资源,子进程就会成为僵尸进程(zombies)。如果进程资源始终占用着进程表资源,将进程表资源耗尽,使得系统无法再创建新的进程。如果父进程终止了,那么僵尸进程会被系统一号进程领养,并由一号进程自动执行 wait 调用,将僵尸进程清理、将所占用的资源回收。
关于这个几个函数的使用细节可以查看 man 手册,有以下几点值得注意:
- 如果父进程在调用 wait 函数时,子进程的状态已经发生了变化,那么调用会立即返回,否则,会阻塞。但是这个行为可以通过options参数进行配置, options 是一个位控制参数, options 配置上
WNOHANG时可以是调用不阻塞,而是立即返回。 - 默认情况下 wait 函数只等待 子进程退出进入终结态的情况,这个行为可以通过options参数进行配置,配置上
WUNTRACED时可以 wait 子进程进入 stop 状态,配置上WCONTINUED可以 wait 处于 stop 状态中的进程被 SIGCONT 信号唤醒。 - status 参数不为 NULL 时,可以接受进程状态变化的相关信息,这些信息可以通过 相关宏对 status 处理得到。
- 当 对非子进程调用 wait 系列函数时,会返回错误 ECHILD。
当 对非子进程调用 wait 系列函数时,会返回错误 ECHILD。那么为什么呢?