为什么需要等待子进程退出?
创建子进程的目的就是为了让子进程去实现某些功能,子进程退出也分为两种,正常退出和不正常退出
正常退出:
main函数调用return
进程调用exit(),标准c库
进程调用_exit()或者_Exit() , 这属于系统调用
进程最后一个线程返回
最后一个线程调用 pthread_exit
不正常退出:
调用abort
当进程收到某些信号时,如ctrl + c
最后一个线程对取消(cancellation)请求做出响应
子进程退出状态不被收集,就变成僵尸进程(zombie)
现在有子进程退出而不被回收的代码
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
int cnt = 0;
pid_t pid;
pid = vfork();
if(pid > 0){
while(1){
printf("this is father print, pid = %d\n", getpid());
sleep(1);
printf("cnt = %d\n",cnt);
}
}else if(pid == 0){
while(1){
printf("this is child print, pid = %d\n", getpid());
sleep(1);
cnt++;
if(cnt == 3){
exit(0);
}
}
}
return 0;
}

如何防止子进程变成僵尸进程
调用wait()
现在我们的代码也是让子进程执行三次退出,只不过在父进程调用了wait
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
int cnt = 0;
pid_t pid;
pid = fork();
if(pid > 0){
wait(NULL); // 父进程调用wait
while(1){
printf("this is father print, pid = %d\n", getpid());
sleep(1);
printf("cnt = %d\n",cnt);
}
}else if(pid == 0){
while(1){
printf("this is child print, pid = %d\n", getpid());
sleep(1);
cnt++;
if(cnt == 3){
exit(0);
}
}
}
return 0;
}

现在研究一下wait方法
方法原型
pid_t wait(int *status);
stauts参数可以是哪些?
可以是一个整型数指针
非空时,子进程退出状态放在它所指向的地址中
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
int cnt = 0;
int status = 10;
pid_t pid;
pid = fork();
if(pid > 0){
wait(&status);
printf("status =%d\n",WEXITSTATUS(status));
while(1){
printf("this is father print, pid = %d\n", getpid());
sleep(1);
printf("cnt = %d\n",cnt);
}
}else if(pid == 0){
while(1){
printf("this is child print, pid = %d\n", getpid());
sleep(1);
cnt++;
if(cnt == 3){
exit(3); // exit里面的值会传递到status,这是系统的设计
}
}
}
return 0;
}
注意:需要使用系统设计的宏才能准确的获取到status的值。


空时:不用关心退出状态,上面的例子就是为空状态(wait(NULL))
与之对应还有一个waitpid()
区别是:
wait() 会阻塞,waitpid()有一个选项可以实现不阻塞
不阻塞情况下,子进程也会编程僵尸进程
函数原型:

waitpid的options常量

用法:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
pid_t pid;
int cnt = 0;
int status = 10;
pid = fork();
if(pid > 0){
//wait(&status);
waitpid(pid, &status, WNOHANG);
printf("child quit child status = %d\n", WEXITSTATUS(status));
while(1){
printf("this is father print, pid = %d\n", getpid());
sleep(1);
printf("cnt = %d\n",cnt);
}
}else if(pid == 0){
while(1){
printf("this is child, child pid = %d\n",getpid());
sleep(1);
cnt++;
if(cnt == 5){
exit(3);
}
}
}
return 0;
}

子进程变成了僵尸进程
