子進程的異步等待方式

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萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章