1. 程式人生 > >signal之——異步回收機制

signal之——異步回收機制

接收 lib tchar getc sign RR exit () child

前言:回收子進程之前用了wait()和非阻塞模型,今天學了信號以後可以使回收機制更上一層樓,通過信號函數,父進程只需要做自己的事情,接收到信號後就觸發信號函數。

信號處理函數可能會出現的bug:

  1.受到停止信號也會觸發SIGCHLD信號,使wait阻塞;

  2.停止後繼續也會觸發信號,導致父進程阻塞;

  3.調用sigaction(),人為發送一個SIGCHLD信號也會使父進程阻塞;

  4.多個進程同時結束,可能造成回收不完全,產生僵屍進程(同中信號不排隊);

解決方案的終極代碼:

//異步回收子進程
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>

#define NR 40

/*
* bugs:如果多個進程同時結束 可能造成回收不完全 產生僵屍進程 (同種信號不排隊)
* 循環方式waitpid解決以上bugs
*/
void waitChild(int signo)
{
pid_t pid;
printf("a sig recv:%d\n",signo);
if(signo!=SIGCHLD) return;

while(1)  //保證觸發一次信號,回收所有結束的子進程
{
pid=waitpid(-1,NULL,WNOHANG|WUNTRACED);//保證非阻塞,以及停止不觸發信號
printf("wait child:%d\n",pid);

if(pid==0||pid==-1)
break;
}
}


int main(void)
{
pid_t pid;

#if 0
//子進程結束或停止 或者從停止到繼續 發生SIGCHLD信號
if(signal(SIGCHLD,waitChild)==SIG_ERR)
{
perror("signal");
return 2;
}
#else
struct sigaction ac={.sa_handler=waitChild};//處理函數
sigemptyset(&ac.sa_mask);//不期望屏蔽其它信號
ac.sa_flags=SA_NOCLDSTOP;//進程停止時不發生SIGCHLD信號
sigaction(SIGCHLD,&ac,NULL);
#endif //

int i;
for(i=0;i<NR;i++)
{
pid=fork();
if(pid==-1) return 1;//error
else if(pid==0)//child
{
printf("%dth child <%d> start work.\n",i,getpid());
sleep(3);
printf("%dth child <%d> end work.\n",i,getpid());
exit(0);
}
}
//parent
while(1)
{
getchar();
printf("parent working....\n");
}

return 0;
}

signal之——異步回收機制