










waitpid()函数实际上用于等待子进程的状态变化,并为父进程提供子进程的终止状态信息。
当一个子进程终止时,操作系统会向父进程发送 SIGCHLD 信号。在处理这个信号的过程中,
父进程通常会使用 waitpid()函数来获取子进程的状态信息,以便执行相应的操作(如回收资源)。
waitpid() 函数可以等待子进程的以下几种状态变化:
waitpid() 函数的功能不仅限于等待 SIGCHLD信号。它实际上为父进程提供了一种在子进程状态变化时收集信息和执行操作的机制。
这有助于避免僵尸进程的产生,并允许父进程对子进程的状态变化做出响应。
pid:指定要等待的子进程的进程 ID。有以下几种取值:
status:一个指向整数的指针,用于存储子进程的终止状态。
您可以使用一些宏(如 WIFEXITED、WEXITSTATUS 等)来分析这个状态值。
options:提供额外的选项来控制waitpid()函数的行为。主要有以下几种选项:
如果成功,waitpid() 函数返回一个子进程的进程 ID。
如果使用了 WNOHANG 选项且没有子进程已经终止,waitpid() 函数返回 0。
如果发生错误,waitpid() 函数返回 -1,并设置 errno。
在信号处理函数中使用 waitpid() 函数和 WNOHANG 选项的一个典型场景是
处理子进程终止时发送的 SIGCHLD信号。
通过在信号处理函数中使用循环,您可以确保在一次信号处理函数调用中处理所有已终止的子进程。
这种方法在多个 SIGCHLD 信号被合并的情况下尤其有效,能避免僵尸进程的产生。
WNOHANG 参数的作用
如果两个子进程几乎同时终止,它们各自发送的 SIGCHLD 信号可能会被合并为一个信号,导致信号处理函数只被调用一次。
然而,通过在信号处理函数中使用 waitpid() 函数并设置 WNOHANG 选项,仍然可以处理这种情况。
WNOHANG 选项本身并不能保证处理所有子进程。
while((mypid=waitpid(-1, NULL, WNOHANG)) > 0) { // 业务处理 }
信号处理函数如上实现仍出现僵尸进程原因如下
Unix/Linux 的信号机制中,相同信号不会排队
(如果短时间内有 100 个子进程退出,内核只会向父进程发送 1 次 SIGCHLD 信号,而不是 100 次)
上述处理函数能清理信号触发时已退出的子进程,但如果处理函数执行过程中,又有新的子进程退出,
这些新退出的子进程不会触发新的 SIGCHLD(因为信号还在处理中,内核不会重复发送),直到处理函数执行完
而大规模子进程退出时,处理函数执行和子进程退出几乎同时发生,
必然有部分子进程退出在信号处理窗口外成为僵尸进程。
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。