一.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;
}
結果如下: