eg1:
// waitpid1.c // 2015-08-26 Lucifer Zhang // Using the waitpid function to reap zombie children in no // particular order. #include "csapp.h" #define N 2 int main() { int status, i; pid_t pid; /* Parent creates N children */ for (i = 0; i < N; i++) //line:ecf:waitpid1:for if ((pid = Fork()) == 0) /* child */ //line:ecf:waitpid1:fork exit(100+i); //line:ecf:waitpid1:exit /* Parent reaps N children in no particular order */ while ((pid = waitpid(-1, &status, 0)) > 0) { //line:ecf:waitpid1:waitpid if (WIFEXITED(status)) //line:ecf:waitpid1:wifexited printf("child %d terminated normally with exit status=%d\n", pid, WEXITSTATUS(status)); //line:ecf:waitpid1:wexitstatus else printf("child %d terminated abnormally\n", pid); } /* The only normal termination is if there are no more children */ if (errno != ECHILD) //line:ecf:waitpid1:errno unix_error("waitpid error"); exit(0); }第15行,父进程创建N个子进程,在第16行,每个子进程以一个唯一的退出状态退出。在第19行,父进程用waitpid作为while循环的测试条件,等待它所有的子进程终止,因为第一个参数是-1,所以对waitpid的调用会阻塞,知道任意一个子进程终止。在每个子进程终止时,对waitpid的调用会返回,返回值为该子进程的非零PID。第20行检查子进程的退出状态。如果子进程是正常终止的,在此是以调用exit函数终止的,那么父进程就提取出退出状态,把它输出到stdout上。
当回收了所有的子进程之后,再调用waitpid就返回-1,并且设置errno为ECHILD。第28行检查waitpid函数是正常终止的,否则就输出一个错误消息。
测试:
注意,程序不会按照特定的顺序回收子进程。子进程回收的顺序是这台特定的计算机的属性。在另一个系统上,甚至在同一个系统上再次执行一次,两个子进程都可能以相反的顺序被回收。上面的测试结果也说明了这一点。这是非确定性的(nondeterministic)行为的一个示例,这种非确定性行为使得对并发进行推理非常困难。
下面这个例子做了简单的改变,消除了不确定性,按照父进程创建子进程的相同顺序来回收这些子进程。
eg2:
// waitpid1.c // 2015-08-26 Lucifer Zhang // Using waitpid to reap zombie children in the order they were created. #include "csapp.h" #define N 2 int main() { int status, i; pid_t pid; /* Parent creates N children */ for (i = 0; i < N; i++) //line:ecf:waitpid1:for if ((pid = Fork()) == 0) /* child */ //line:ecf:waitpid1:fork exit(100+i); //line:ecf:waitpid1:exit /* Parent reaps N children in no particular order */ while ((pid = waitpid(-1, &status, 0)) > 0) { //line:ecf:waitpid1:waitpid if (WIFEXITED(status)) //line:ecf:waitpid1:wifexited printf("child %d terminated normally with exit status=%d\n", pid, WEXITSTATUS(status)); //line:ecf:waitpid1:wexitstatus else printf("child %d terminated abnormally\n", pid); } /* The only normal termination is if there are no more children */ if (errno != ECHILD) //line:ecf:waitpid1:errno unix_error("waitpid error"); exit(0); }
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/zyq522376829/article/details/48003537