一.SIGCHLD
SIGCHLD信号:当子进程退出时,它会向父进程发送SIGCHLD信号,该信号的默认处理方式为忽略,当父进程以阻塞方式等待时,它不能处理自己的工作。
我们自定义一个捕捉信号的函数catchsig。
代码如下:
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>
void catchsig(int sig)
{
printf("get a sig:%d,pid:%d\n",sig,getpid());
}
int main()
{
signal(SIGCHLD,catchsig);
pid_t id=fork();
if(id==0)
{//child
printf("I am child,quit! pid:%d\n",getpid());
exit(1);
}
else
{//father
waitpid(id,NULL,0);//以阻塞方式等待
}
return 0;
}
结果如图所示:
子进程退出,向父进程发送信SIGCHLD,父进程会调用SIGCHLD的捕捉函数。
二. 父进程等待子进程的异步方式
父进程自定义SIGCHLD信号的处理函数,并采用非阻塞方式等待,当子进程退出时,会向父进程发送信号,父进程会进行回收。
当有10个子进程退出时,会给父进程发送10个信号,但由于只会记录一次,所以只能回收一次,我们让父进程一直回收,当子进程全部被回收完时,waitpid()会出错返回。
代码如下:
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>
void catchsig(int sig)
{
do
{
pid_t ret=waitpid(-1,NULL,WNOHANG);//-1表示可以回收任何进程,WNOHANG表示非阻塞方式等待
if(ret>0)
{
printf("wait success:%d\n",ret);
}
else
{
printf("wait filed:%d\n",ret);
break;
}
}while(1);
}
int main()
{
signal(SIGCHLD,catchsig);
pid_t id=fork();
if(id==0)
{//child
printf("I am child,quit! pid:%d\n",getpid());
exit(1);
}
else
{//father
while(1)
{
printf("do father things!\n");
sleep(1);
}
}
return 0;
}
结果如下: