一、进程等待的作用
我们都知道,当子进程已经结束而父进程还在执行时,子进程会变成僵尸进程,造成内存泄漏等问题,如下:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
#include <sys/wait.h>int main()
{pid_t id = fork();if(id == 0){int i = 5;while(i--){printf("I am child, mypid is : %d\n", getpid());sleep(1);}}else {while(1){printf("I am father : %d\n", getpid());sleep(3);}}return 0;
}
僵尸进程的危害十分严重,为了防止僵尸进程,及时地回收资源,我们可以采用进程等待的方式。
进程等待有两点主要作用: 1、父进程通过等待,回收子进程的资源。 2、父进程通过等待,获取子进程的退出信息。
二、进程等待的系统调用
进程等待一般通过两个接口:wait() 以及 waitpid() 。
1、wait() 的作用是等待任意一个子进程,默认为阻塞等待(等待时父进程阻塞,不能做其他事)。返回值:成功,返回等待的子进程的pid;失败,返回 -1。参数:输出型参数,返回的是对应子进程的退出信息。
2、status:status有32位,我们只看低16位,0-6 低 7 位表示退出时收到的信号,7表示core dump 标识,8-15 也就是次低八位表示退出码。
3、waitpid()的作用也是等待,但它可以更细致的控制。参数:pid 的解释如下:
我们一般用两个,pid == 0 表示等待任意一个子进程;pid > 0 表示等待进程ID==pid的进程。status是输出型参数,如解释 2。options 表示是否进行阻塞等待,0表示阻塞等待,1表示非阻塞等待,也可以用宏,WNOHANG表示非阻塞等待,WUNTRACED表示阻塞等待。
返回值:在阻塞状态下,成功返回子进程pid,失败返回 -1;在非阻塞状态下,成功返回子进程pid,还在等返回0,失败返回 -1.
测试代码:status次低八位是退出码,低七位是退出信号。
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>int main()
{pid_t id = fork();if (id == 0){int i = 5;while (i--){printf("I am child, mypid is : %d\n", getpid());sleep(1);}exit(30);//退出码}else{int status = 0;waitpid(id, &status, 0);printf("childprocess has exited, exit code : %d, exit signal : %d\n", (status>>8)&0xff, status & 0x7f);sleep(1);}return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>int main()
{pid_t id = fork();if (id == 0){int i = 5;while (i--){printf("I am child, mypid is : %d\n", getpid());sleep(1);}i /= 0;//退出信号:浮点错误 8 exit(30);}else{int status = 0;waitpid(id, &status, 0);printf("childprocess has exited, exit code : %d, exit signal : %d\n", (status>>8)&0xff, status & 0x7f);sleep(1);}return 0;
}
我们也可以用宏来代替位操作来得到退出码和退出信号。
WEXITSTATUS(status) 表示退出码, WTERMSIG(status) 表示退出信号 (更多在man手册查看)