DevOps wait,waitpid,waitid,wait3,wait4函数详解

mustang2012 · December 26, 2019 · 127 hits

对于许多需要创建子进程的应用来说,父进程能够监测子进程的终止时间和过程是很有必要的,wait 以及相关系统调用函数提供了这一功能

1
2

pid_t wait(int *status);

系统调用 wait 执行如下动作:

  • 如果调用进程并无之前未被等待的子进程终止,调用将一直阻塞,直至某个子进程终止。如果调用时已有子进程终止,wait 则立即返回。
  • 如果 status 非空,那么关于子进程的如何终止的信息则会通过 status 指向的正序变量返回。
  • 内核将会为父进程下所有子进程的运行总量追加进程 CPU 时间以及资源使用。
  • 将终止子进程的 id 作为 wait 的结果返回。
    可能出错的原因之一是调用进程并没有之前未被等待的子进程。此时会将 errno 置为 ECHILD。

可以这样来等待调用进程的所有子进程终止:

1
2
3
4
while((childid = wait(NULL)) != -1)
continue;
if(errno == ECHILD)
exit(0);

waitpid 函数

系统调用 wait 存在诸多限制,而 waitpid 则突破了这些限制:

  • 如果父进程已经创建了多个子进程,使用 wait 将无法等待某个特定子进程的完成,只能按顺序等待下一个子进程的终止。
  • 如果没有子进程退出,wait 将一直保持阻塞,有时希望执行非阻塞的等待:是否有子进程退出,立判可知。
  • 使用 wait 只能发现那些已经终止的子进程。子进程因某个信号而停止,或是已停止的信号因收到 SIGCONT 信号后恢复执行的情况无法知晓。(停止与终止不同,停止即暂停、挂起,终止即 over)
1
2

pid_t waitpid(pid_t pid,int *status,int options); //成功返回子进程id,出错返回0或-1

status 与 wait 中的意义相同。参数 pid 用来表示需要等待的具体子进程:

  • 如果 pid 大于 0,表示等待进程 id 为 pid 的子进程。
  • 如果 pid 等于 0,表示等待与调用进程同一个进程组的所有子进程。
  • 如果 pid 小于-1,则会等待进程组标识符与 pid 的绝对值相等的所有子进程。
  • 如果 pid 等于-1,则会等待任意子进程,等价于 wait(&status)。

参数 options 是一个位掩码,可以包含 0 个或多个标志:
WUNTRACED:除了返回终止子进程的信息外,还返回因信号而停止的子进程信息。
WCONTINUED:返回那些因收到 SIGCONT 信号而恢复执行的已停止子进程的状态信息。
WNOHANG:如果参数 pid 所指定的子进程并未发生状态变化,则立即返回不会阻塞。这种情况下 waitpid 返回 0。

waitid 函数

与 waitpid 类似,waitid 返回子进程的状态,不过 waitid 提供了 waitpid 所没有的扩展功能。

1
2
3

int (idtype_t idtype,id_t id,siginfo_t *infop,int options);
//成功或者WNOHANG时无子进程改变时返回0,出错返回-1

参数 idtype 和 id 指定需要等待哪些子进程:

  • 如果 idtype 为 P_ALL,则等待任何子进程,同时忽略 id 值。
  • 如果 idtype 为 P_PID,则等待进程 id 为 id 进程的子进程。
  • 如果 idtype 为 P_PGID,则等待进程组 id 为 id 的所有子进程。

注:与 waitpid 不同,不能靠指定 id 为 0 来表示与调用者属于同一进程租的所有进程,必须以 getpgrp 函数的返回值来显式指定调用者的进程组 id
waitpid 与 waitid 最显著的区别在于,对于应该等待的子进程事件,waitid 可以更为精确的控制。可以通过在 options 中指定一个或多个标识来实现控制:
WEXITED :等待已终止的子进程,无论其是否正常返回。
WSTOPPED:等待已通过信号而停止的子进程。
WCONTINUED : 等待经由信号 SIGCONT 而恢复的子进程。
WNOHANG:如果匹配 id 值的子进程中无状态信息需要返回,则立即返回而不阻塞。
WNOWAIT:会返回子进程状态,但是子进程依然处于可等待状态,稍后可以再次等待并获取相同的信息。
执行成功返回 0,并更新指针 infop 所指向的 siginfo_t 结构,其包含子进程的相关信息。

wait3 和 wait4 函数

wait3 和 wait4 函数执行与 waitpid 类似的工作,主要的语义差别在于,wait3 和 wait4 在参数 rusage 所指向的结构中返回终止子进程的资源使用情况。其中包括进程使用的 CPU 时间总量以及内存管理的统计数据。

1
2
3
4
5
6
#define _BSD_SOURCE
#include<sys/resource.h>

pid_t wait3(int *status,int options,struct resage *rusage);
pid_t wait4(pid_t pid,int *status,int options,struct rusage *rusage);

除了对参数 rusage 的使用外,调用 wait3 等价于:waitpid(-1,&status,options);
类似的 wait4 等价于:waitpid(pid,&status,options);
也就是说,wait3 等待的是任意子进程,而 wait4 等待的是选定的一个或多个子进程。
但是其实 wait3 和 wait4 的返回值没什么价值,此外这两函数的移植性比较差。尽量不要用…


参考资料:
《linux/UNIX 系统编程手册 上》(tlpi)
《UNIX 环境高级编程 3th》(APUE)

No Reply at the moment.
You need to Sign in before reply, if you don't have an account, please Sign up first.