原文网址:http://blog.163.com/libo_5/blog/static/15696852010324287748/
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,则结束的进程的termination status会被保存在statiloc所指向的内存的区域;如果我们不关心termination status,则可以把statloc置为NULL。 传统的实现中这两个函数返回的整数中特定的比特位被赋予了特定的含义。POSIX.1指定了一些包含在头文件<sys/wait.h> 宏来查看这些termination status Macro Description WIFEXITED(status) 如果status是由一个正常结束的进程产生的则值为真, 此时我们可以继续使用宏WEXITSTATUS(status)来 获取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支持工作控制 具体可以查看APUE page202 |
===========================================================================
进程一旦调用了wait,就立即阻塞自己,由wait自动分析是否当前进程的某个子进程已经退出,如果让它找到了这样一个已经变成僵尸的子进程,wait 就会收集这个子进程的信息, 并把它彻底销毁后返回;如果没有找到这样一个子进程,wait就会一直阻塞在这里,直到有一个出现为止。
wait(等待子进程中断或结束)相关函数 waitpid,fork表头文件#include<sys/types.h>#include<sys/wait.h>定义函数 pid_t wait (int * status);函数说明wait()会暂时停止目前进程的执行,直到有信号来到或子进程结束。如果在调用wait()时子进程已经结束,则wait()会立即返回子进程结束状态值。子进程的结束状态值会由参数status 返回,而子进程的进程识别码也会一快返回。如果不在意结束状态值,则参数status 可以设成NULL。子进程的结束状态值请参考waitpid()。返回值如果执行成功则返回子进程识别码(PID),如果有错误发生则返回-1。失败原因存于errno 中。附加说明范例 一#include<stdlib.h>#include<unistd.h>#include<sys/types.h>#include<sys/wait.h>int main(){ pid_t pid;int status,i;if(fork()= =0){ printf(“This is the child process .pid =%d\n”,getpid());exit(5);}else{ sleep(1);printf(“This is the parent process ,wait for child...\n”;pid=wait(&status);i=WEXITSTATUS(status);printf(“child’s pid =%d .exit status=%d\n”,pid,i);}}执行This is the child process.pid=1501This is the parent process .wait for child...child’s pid =1501,exit status =5
范例 二
#include<iostream>#include<unistd.h>#include<sys/wait.h>using namespace std;int main(void){ pid_t pid; pid =fork(); if (pid<0) exit(0); else if (pid == 0) { //如果是子进程 睡眠20秒 cout<<"children : "<<getpid()<<endl; sleep(20); } else { cout<<"hello! i'm parent process!"<<endl; //如果是父进程在这里等待 pid_t pr = wait(NULL); cout<<pr<<endl; } return 0;}waitpid(等待子进程中断或结束)相关函数 wait,fork表头文件#include<sys/types.h>#include<sys/wait.h>定义函数 pid_t waitpid(pid_t pid,int * status,int options);函数说明waitpid()会暂时停止目前进程的执行,直到有信号来到或子进程结束。如果在调用waitpid()时子进程已经结束,则waitpid()会立即返回子进程结束状态值。子进程的结束状态值会由参数status 返回,而子进程的进程识别码也会一快返回。如果不在意结束状态值,则参数status 可以设成NULL。参数pid 为欲等待的子进程识别码,其他数值意义如下:pid<-1 等待进程组识别码为pid 绝对值的任何子进程。pid=-1 等待任何子进程,相当于wait()。pid=0 等待进程组识别码与目前进程相同的任何子进程。pid>0 等待任何子进程识别码为pid 的子进程。参数option 可以为0 或下面的OR 组合:WNOHANG 如果没有任何已经结束的子进程则马上返回,不予以等待。WUNTRACED 如果子进程进入暂停执行情况则马上返回,但结束状态不予以理会。子进程的结束状态返回后存于status,底下有几个宏可判别结束情况:WIFEXITED(status)如果子进程正常结束则为非0 值。WEXITSTATUS(status)取得子进程exit()返回的结束代码,一般会先用WIFEXITED 来判断是否正常结束才能使用此宏。WIFSIGNALED(status)如果子进程是因为信号而结束则此宏值为真WTERMSIG(status) 取得子进程因信号而中止的信号代码,一般会先用WIFSIGNALED 来判断后才使用此宏。WIFSTOPPED(status) 如果子进程处于暂停执行情况则此宏值为真。一般只有使用WUNTRACED 时才会有此情况。WSTOPSIG(status) 取得引发子进程暂停的信号代码,一般会先用WIFSTOPPED 来判断后才使用此宏。返回值如果执行成功则返回子进程识别码(PID),如果有错误发生则返回-1。失败原因存于errno 中。范例参考wait()。