wait()、waitpid()及waitid()介绍

来源:互联网 发布:淘宝客源码卷皮 编辑:程序博客网 时间:2024/06/12 00:44

这三个函数的原型如下:

       #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);

这三个系统调用是用来让调用进程等待其子进程状态更改,并获取这种状态改变信息的。子进程的状态更改是指1>子进程终止;2>子进程被一个信号暂停;3>子进程收到一个信号重新运行了。对于第一种情况,执行这三个系统调用可以使得系统收回结束子进程占用的资源,如果子进程终止了,但我们没有执行这三个中的任何一个,则子进程将变为“僵尸进程”,僵尸进程也会占用一部分系统资源,所以我们应该尽可能的避免系统中存在过多的僵尸进程。

pid_t wait(int *status):该调用会阻塞调用进程,直到其某个子进程终止(注意是终止)或者调用进程自己被一个信号处理打断了。对于第二种情况我们应该注意,如果这不是我们期望的结果,我们应该想办法重启该系统调用。可用如下方法重启:

#include <errno.h>
#include <sys/types.h>
pid_t r_wait(int *stat_loc)
{
       pid_t child_pid;

       while (((child_pid =wait(stat_loc) )== -1) && (errno == EINTR));
        return child_pid;
}

参数stat_loc用来获取子进程的状态更改信息,后面会介绍如何解析这种状态;如果我们不关注其具体状态更改是什么,调用是可传递NULL。

pid_t waitpid(pid_t pid, int *status, int options):这个功能最丰富,也是最好用的一个。默认情况下,调用其会阻塞调用进程直到指定的子进程状态发生改变,这种行为可以通过参数options改变。成功则返回子进程id,如果指定了WNOHANG,并且此时pid指定的子进程有多个,但是它们的状态还没有发生改变,这时返回0,出错返回-1。其参数描述如下

pid的可能值为:

  • <-1:意味着等待的子进程为pid的绝对值标识的进程组中的任意一个
  • =-1:意味着等待其任意一个子进程
  • =0:意味着等待和调用进程在同一个进程组中的任意子进程
  • >0:意味着等待的子进程的进程id为指定值

options的值可以为如下三个值的或操作组合:

  • WNOHANG:设置该参数调用进程不会被阻塞,不论子进程状态有无改变,立即返回
  • WUNTRACED:设置该参数使得当子进程暂停时也会返回。对于这个参数,还有一些描述我没有弄明白,若有弄明白的不妨指点一下,不甚感谢。
  • WCONTINUED:设置该参数后,当等待的子进程收到信号SIGCONT,由暂停状态变为运行状态后也会返回。

如果调用时,status不是NULL,则子进程的状态将会被存储到这个整形参数中,我们可以用如下宏检查这个值,这些宏的参数是整形值本身,不是其指针:

  • WIFEXITED(status):如果子进程正常终止返回true,当子进程有return、exit()或_exit()返回时为正常终止。
  • WEXITSTATUS(status):返回子进程的终止状态(由return、exit()或_exit()返回的),是一个8位值,这个宏应该在确定WIFEXITED返回true时再使用
  • WIFSIGNALED(status):如果子进程是被一信号终止的则返回true
  • WTERMSIG(status):返回造成子进程终止的信号的数目,这个宏应该在确定WIFSIGNALED返回true时再使用
  • WCOREDUMP(status):如果子进程产生一个core dump时返回true,这个宏应该在确定WIFSIGNALED返回true时再使用,并且应该用#ifdef WCOREDUMP ...#endif抱起来,这个宏在有些版本上是不适用的。
  • WIFSTOPPED(status):当子进程被暂停时返回true,这只可能出现在使用WUNTRACED调用waitpid或者子进程确实是正在被跟踪(调试时).
  • WSTOPSIG(status):返回造成子进程暂停的信号的数目,这个宏应该在WIFSTOPED返回true时使用
  • WSTOPSIG(status):在linux 2.6.10版本后可以使用,当子进程收到信号SIGCONT后由暂停状态回到运行状态时返回true

int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options):这个调用适用与linxu 2.6.9之后,它对等待的是哪一个子进程提供了更加精确的控制。执行成功或者指定了WNOHANG,但是id所指的子进程状态没有发生改变时返回0;出错返回-1。

idtype和id配合使用来指定等待的是哪一个子进程,idtype的值可以有:

  • = P_PID:等待的子进程的pid必须和id匹配
  • = P_GID:等待的子进程的组id需和id匹配
  • = P_ALL:等待所有子进程,此时id被忽略

options的值可以为如下几个的或操作组合:

  • WEXITED:等待那些已经终止的子进程
  • WSTOPPED:等待那些被信号暂停的子进程
  • WCONTINUED:等待那些由SIGCONT重新启动的子进程
  • WNOHANG:同wiatpid中的
  • WNOWAIT:从处于”可等待状态“的子进程返回,但是后面的wait还可以获取子进程的状态

如果infop不为NULL,则档waitid成功返回时,这个结构将会被填写,我们可以从该结构中获取我们感兴趣的信息,其中有:

  • si_pid: 子进程的进程id
  • si_uid:子进程的真实用户id
  • si_signo:总是设置为SIGCHID
  • si_status:要么是子进程的返回状态,要么是造成子进程状态改变的信号,si_code说明如何来解释这个域
  • si_code:可以设置为CLD_EXITED、CLD_KILLED、CLD_DUMPED、CLD_STOPPED、 CLD_TRAPPED 、CLD_CONTINUED,哪种情况为哪个值一看名字就能明白

当出错返回时,这三个调用都应该检查如下errno:ECHILD、EINTR、EINVAL。


以上内容来自linux联机帮助文档。。。。