wait和waitpid详解

zombie不占用内存也不占用CPU,表面上我们可以不用在乎它们的存在,然而事实上UNIX系统限制了某一时刻能同时存在的进程的最大数目。如果程序不及时清理系统中的zombie,最终会导致进程数过多,当再次需要产生新进程时就会出错。
 

  鉴于上边的原因,我们需要在子进程调用exit后在父进成中调用wait或waipid
#include<sys/types.h>
#include<sys/wait.h>
pid_t wait(int &statloc);
pid_t waitpid(pid_t pid,int *statloc, int options);
Both return:process ID if OK,-1 on error
   它们被父进程调用以获取子进程结束信息、清除zombie。当父进成调用这两个函数时
a 阻塞(如果它的子进程还在运行)
b 立即返回子进程结束信息(如果一个子进程已经结束并等待父进程获取信息)
c 返回错误(如果不存在子进程)

    两个函数的不同在于wait会令调用者阻塞直至某个子进程终止而waitpid则可以通过设置一个选项来设置为非阻塞,另外waitpid并不是等待第一个结束的进程而是等待参数中pid指定的进程。
   两个函数中的变量statloc是一个指向int型数据的指针。如果此变量不是NULL,则结束的进程的terminationstatus会被保存在statiloc所指向的内存的区域;如果我们不关心terminationstatus,则可以把statloc置为NULL。

    传统的实现中这两个函数返回的整数中特定的比特位被赋予了特定的含义。POSIX.1指定了一些包含在头文件<sys/wait.h>宏来查看这些termination status

 

Macro

Description

WIFEXITED(status)

如果status是由一个正常结束的进程产生的则值为真,此时我们可以继续使用宏WEXITSTATUSstatus)来 获取exit_exit的参数

WIFSIGNALED(status)

如果status是由一个异常结束(接受到一个信号)的进程产生的则值为真,此时使用宏WTERMSIG(status)来获取信号数。

WIFSTOPPED(status)

如果status是由一个接受到信号目前终止的进程产生的 则值为真,此时可以继续调用宏WSTOPSIG(status)来查看是哪个信号导致进程终止。

 


   waitpid的option常量:
WNOHANG  waitpid将不阻塞如果指定的pid并未结束
WUNTRACED 如果子进程进入暂停执行情况则马上返回,但结束状态不予以理会。


 

  waitpid中pid的含义依据其具体值而变:
pid==-1 等待任何一个子进程,此时waitpid的作用与wait相同
pid >0  等待进程ID与pid值相同的子进程
pid==0  等待与调用者进程组ID相同的任意子进程
pid<-1  等待进程组ID与pid绝对值相等的任意子进程

   waitpid提供了wait所没有的三个特性:
1 waitpid使我们可以等待指定的进程
2 waitpid提供了一个无阻塞的wait
3 waitpid支持工作控制



也可以用消息队列吧,子进程退出前把自已的PID写进队列
然后父进程去读,不过pid = waitpid(-1, &stat, 0);
让父进程阻塞在调用这块,不过如果你想让waitpid快带返回也行, 如果没接到子进程退出信号,你可以把这个PID再写进去,然后继续读,直到接到SIGCHLD为止。

以前在项目中遇到过此问题,大量的并发进程往往造成很多的僵死进程,以至于程序无法响应,当时被这个问题弄得很头痛,直到想到这个方法以后才有效的解决了上述问题。

为方法就等于实现了一个对SIGCHLD的排队机制。我一直在大型的项目中用这个,很不错。

你可能感兴趣的:(wait和waitpid详解)