linux waitpid函数详解

简介: linux waitpid函数详解

linux waitpid函数详解

函数的作用

waitpid() 函数实际上用于等待子进程的状态变化,并为父进程提供子进程的终止状态信息。当一个子进程终止时,操作系统会向父进程发送 SIGCHLD 信号。在处理这个信号的过程中,父进程通常会使用 waitpid() 函数来获取子进程的状态信息,以便执行相应的操作(如回收资源)。

waitpid() 函数可以等待子进程的以下几种状态变化:

  1. 子进程正常终止:子进程执行完毕或调用 exit() 函数。
  2. 子进程被信号终止:子进程因接收到一个信号(如 SIGKILL)而被终止。
  3. 子进程被暂停:当使用 WUNTRACED 选项时,waitpid() 函数还可以返回因接收到 SIGSTOP 而暂停的子进程的状态。
  4. 子进程恢复执行:当使用 WCONTINUED 选项时,waitpid() 函数还可以返回因接收到 SIGCONT 而恢复执行的子进程的状态。

waitpid() 函数的功能不仅限于等待 SIGCHLD 信号。它实际上为父进程提供了一种在子进程状态变化时收集信息和执行操作的机制。这有助于避免僵尸进程的产生,并允许父进程对子进程的状态变化做出响应。

函数原型

waitpid() 函数是一个用于等待子进程状态变化的系统调用。它可以让父进程在子进程结束时收到通知,从而避免僵尸进程的产生。waitpid() 函数的原型如下:

#include <sys/types.h>
#include <sys/wait.h>
pid_t waitpid(pid_t pid, int *status, int options);

参数说明:

  1. pid:指定要等待的子进程的进程 ID。有以下几种取值:
  • pid > 0:等待指定 PID 的子进程。
  • pid == -1:等待任何子进程。此时,waitpid() 的行为类似于 wait() 函数。
  • pid == 0:等待同一进程组中的任何子进程。
  • pid < -1:等待指定进程组 ID 的绝对值的任何子进程。
  1. status:一个指向整数的指针,用于存储子进程的终止状态。您可以使用一些宏(如 WIFEXITEDWEXITSTATUS 等)来分析这个状态值。
  2. options:提供额外的选项来控制waitpid()函数的行为。主要有以下几种选项:
  • WNOHANG:使 waitpid() 函数在没有子进程终止时立即返回,而不会阻塞。
  • WUNTRACED:除了已终止的子进程外,还返回因接收到 SIGSTOP 而停止的子进程的状态。
  • WCONTINUED:返回因接收到 SIGCONT 而继续运行的子进程的状态。

返回值:

  • 如果成功,waitpid() 函数返回一个子进程的进程 ID。
  • 如果使用了 WNOHANG 选项且没有子进程已经终止,waitpid() 函数返回 0。
  • 如果发生错误,waitpid() 函数返回 -1,并设置 errno

在信号处理函数中使用 waitpid() 函数和 WNOHANG 选项的一个典型场景是处理子进程终止时发送的 SIGCHLD 信号。通过在信号处理函数中使用循环,您可以确保在一次信号处理函数调用中处理所有已终止的子进程。这种方法在多个 SIGCHLD 信号被合并的情况下尤其有效,能避免僵尸进程的产生。

WNOHANG 参数的作用

如果两个子进程几乎同时终止,它们各自发送的 SIGCHLD 信号可能会被合并为一个信号,导致信号处理函数只被调用一次。然而,通过在信号处理函数中使用 waitpid() 函数并设置 WNOHANG 选项,您仍然可以处理这种情况。

您是对的,WNOHANG 选项本身并不能保证处理所有子进程。然而,在信号处理函数(如 catch_child())中使用一个循环可以确保处理所有已终止的子进程。

当您在信号处理函数中使用如下循环时:

pid_t wpid;
int status;
while ((wpid = waitpid(-1, &status, WNOHANG)) > 0) {
    if (WIFEXITED(status)) {
        printf("-----------catch child id=%d, status=%d\n", wpid, WEXITSTATUS(status));
    }
}

waitpid() 函数会立即返回,而不会等待子进程终止。循环会检查是否有子进程已经终止,如果有,waitpid() 函数将返回已终止子进程的 PID。当没有更多子进程终止时,waitpid() 会返回 0,并退出循环。

这个循环会在有子进程终止时执行。只要 waitpid() 函数返回的值大于 0,意味着有子进程已经终止,循环将继续执行。当没有更多子进程终止时,waitpid() 会返回 0,并退出循环。

虽然 WNOHANG 选项并不知道有多少个子进程,但这个循环确保了处理所有已终止的子进程。只要有子进程终止,循环将继续执行,直到处理所有子进程。这种方法能够确保在一次信号处理函数调用中处理所有已终止的子进程,避免僵尸进程的产生。

这样一来,即使多个 SIGCHLD 信号被合并,您仍然可以通过这个循环找出所有已终止的子进程,并执行相应的操作。这种方法能够确保在一次信号处理函数调用中处理所有已终止的子进程,避免僵尸进程的产生。

SIGCHID信号

SIGCHLD 信号是一个由操作系统发送给父进程的信号,用于通知父进程子进程状态的变化。当子进程终止、被暂停或恢复时,操作系统会向父进程发送 SIGCHLD 信号。这使得父进程能够得知子进程的状态变化并采取适当的措施,如回收资源,避免僵尸进程的产生。

以下是 SIGCHLD 信号的一些主要用途:

  1. 子进程终止:当子进程正常终止(例如执行完成或调用 exit() 函数)或异常终止(例如收到一个致命信号)时,操作系统会向父进程发送 SIGCHLD 信号。在这种情况下,父进程可以通过调用 wait()waitpid() 函数来回收子进程的资源,以及获取子进程的终止状态。
  2. 子进程被暂停:当子进程因收到 SIGSTOP 信号而被暂停时,操作系统会向父进程发送 SIGCHLD 信号。父进程可以通过调用 waitpid() 函数并使用 WUNTRACED 选项来检测子进程的暂停状态。
  3. 子进程恢复:当子进程因收到 SIGCONT 信号而恢复执行时,操作系统会向父进程发送 SIGCHLD 信号。父进程可以通过调用 waitpid() 函数并使用 WCONTINUED 选项来检测子进程的恢复状态。

默认情况下,当进程收到 SIGCHLD 信号时,信号会被忽略。但是,您可以为 SIGCHLD 信号定义一个信号处理函数来处理子进程的状态变化。这样,在子进程终止或状态发生变化时,信号处理函数会被自动调用,您可以在其中执行相应的操作。

总之,SIGCHLD 信号是一种通知机制,用于告知父进程其子进程状态的变化。这使得父进程能够采取适当的措施,如回收资源和避免僵尸进程的产生。

目录
相关文章
|
存储 Linux
linux中的目录操作函数
本文详细介绍了Linux系统编程中常用的目录操作函数,包括创建目录、删除目录、读取目录内容、遍历目录树以及获取和修改目录属性。这些函数是进行文件系统操作的基础,通过示例代码展示了其具体用法。希望本文能帮助您更好地理解和应用这些目录操作函数,提高系统编程的效率和能力。
502 26
|
Linux
【Linux】System V信号量详解以及semget()、semctl()和semop()函数讲解
System V信号量的概念及其在Linux中的使用,包括 `semget()`、`semctl()`和 `semop()`函数的具体使用方法。通过实际代码示例,演示了如何创建、初始化和使用信号量进行进程间同步。掌握这些知识,可以有效解决多进程编程中的同步问题,提高程序的可靠性和稳定性。
1110 19
|
Linux Android开发 开发者
linux m、mm、mmm函数和make的区别
通过理解和合理使用这些命令,可以更高效地进行项目构建和管理,特别是在复杂的 Android 开发环境中。
1057 18
|
存储 监控 Linux
嵌入式Linux系统编程 — 5.3 times、clock函数获取进程时间
在嵌入式Linux系统编程中,`times`和 `clock`函数是获取进程时间的两个重要工具。`times`函数提供了更详细的进程和子进程时间信息,而 `clock`函数则提供了更简单的处理器时间获取方法。根据具体需求选择合适的函数,可以更有效地进行性能分析和资源管理。通过本文的介绍,希望能帮助您更好地理解和使用这两个函数,提高嵌入式系统编程的效率和效果。
778 13
|
Linux Shell
Linux系统编程:掌握popen函数的使用
记得在使用完 `popen`打开的流后,总是使用 `pclose`来正确关闭它,并回收资源。这种做法符合良好的编程习惯,有助于保持程序的健壮性和稳定性。
1098 6
|
Linux Shell
Linux系统编程:掌握popen函数的使用
记得在使用完 `popen`打开的流后,总是使用 `pclose`来正确关闭它,并回收资源。这种做法符合良好的编程习惯,有助于保持程序的健壮性和稳定性。
628 3
在Linux内核中根据函数指针输出函数名称
在Linux内核中根据函数指针输出函数名称
|
Linux PHP
Linux CentOS 宝塔 Suhosin禁用php5.6版本eval函数详细图文教程
【8月更文挑战第27天】本文介绍两种禁用PHP执行的方法:使用`PHP_diseval_extension`禁用和通过`suhosin`禁用。由于`suhosin`不支持PHP8,仅适用于PHP7及以下版本,若服务器安装了PHP5.6,则需对应安装`suhosin-0.9.38`版本。文章提供了详细的安装步骤,并强调了宝塔环境下与普通环境下的PHP路径差异。安装完成后,在`php.ini`中添加`suhosin.so`扩展并设置`executor.disable_eval = on`以禁用执行功能。最后通过测试代码验证是否成功禁用,并重启`php-fpm`服务生效。
567 2
|
Shell Linux C语言
Linux0.11 execve函数(六)
Linux0.11 execve函数(六)
870 1
|
Linux
Linux0.11 文件打开open函数(五)
Linux0.11 文件打开open函数(五)
282 0