子进程的异步等待方式

SIGCHLD:子进程在终止退出时会给父进程发SIGCHLD信号,该信号的默认处理动作是忽略。

验证如下:创建一个子进程,自定义信号SIGCHLD的捕捉函数,若子进程退出并调用了此信号捕捉函数,则验证成功。

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>

void myhander(int sig)
{
	printf("father get child sig,child exit, sig##%d\n",sig);
}
int main()
{
	signal(SIGCHLD,myhander);

	pid_t id=fork();
	if(id==0)   //child
	{
		printf("child is doing something:child pid##%d\n",getpid());
		sleep(1);
        exit(1);   //子进程退出 
	}
    
    //验证是否发信号SIGCHLD,执行myhander函数
	 
	pid_t ret=waitpid(id,NULL,0);   //阻塞等待子进程  
	if(ret>0)
	{
		printf("wait success!!!child pid##%d\n",ret);
	}	
	return 0;
}
结果如下:验证成功




子进程异步等待方式:

用wait和waitpid函数清理僵尸进程,父进程可以阻塞等待子进程结束,也可以非阻塞地查询是否有子进程结束等待清理(也就是轮询的方式)。采用第一种方式,父进程阻塞了就不能处理自己的工作了;采用第二种方式,父进程在处理自己的工作的同时还要记得不时地轮询一 下,程序实现复杂。

所以由上可知父进程可以自定义SIGCHLD信号的处理函数,这样父进程只需专心处理自己的工作,不必关心子进程了,子进程终止时会发信号通知父进程,父进程在信号处理函数中调用wait清理子进程即可。

代码如下:

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>

void myhander(int sig)   //每个子进程退出发送信号进入此函数 
{
	printf("father get child sig,child exit: sig##%d\n",sig);
	pid_t id;
	while((id=waitpid(-1,NULL,WNOHANG))>0)    //父进程非阻塞等待当前任意退出的子进程 
	{
		printf("wait success!!! child pid##%d\n",id);
	}
}
int main()
{
	signal(SIGCHLD,myhander);   //注册信号处理函数 

	pid_t id1=fork();    //创建子进程1 
	if(id1==0)   //child
	{
		printf("child is doing something:child1 pid##%d\n",getpid());
        exit(1);     //运行完退出 
	} 
    

	pid_t id2=fork();    //创建子进程2 
	if(id2==0)   //child
	{
		printf("child is doing something:child2 pid##%d\n",getpid());
		sleep(2);     
		exit(-1);    //2s后异常退出 
	}
	
	while(1)     //父进程每1s打印一次 
	{
		printf("father is doing something!!!\n");
		sleep(1);
	}

	return 0;
}
以上代码中创建两个子进程第一个直接退出,第二个等待2S退出,则在它们各自退出时间发送信号给父进程,父进程则在各自退出时间执行SIGCHLD信号捕捉函数,等待成功后,若当前暂时再没有了退出的子进程,其则不阻塞等待而去执行自己的工作。

如下结果:





发布了85 篇原创文章 · 获赞 56 · 访问量 9万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章