1. 程式人生 > >子程序的非同步等待方式

子程序的非同步等待方式

通過之前所學的知識,我們可以瞭解到,通過wait函式或者waitpid函式可以清理殭屍程序,父程序可以通過兩種方式等待子程序,一種是阻塞方式,另一種是非阻塞方式,而不管是那種方式,父程序都做不到完全不理會子程序而去完成自己的動作,即子程序不能達到非同步等待的目的。
一、SIGCHLD訊號
1、關於SIGCHLD訊號
子程序在終止時會給父程序發SIGCHLD訊號,該訊號的預設處理動作是忽略,父程序可以自定義SIGCHLD訊號的處理函式,這樣父程序就可以進行自己的動作而不必管理子程序,子程序只需要在退出時通知父程序,父程序在訊號處理函式中呼叫wait函式來清理子程序即可。
2、舉例說明


#include <stdio.h>
#include <unistd.h> #include <stdlib.h> #include <signal.h> #include <sys/types.h> #include <sys/wait.h> void handler(int sig) { do{ pid_t ret=waitpid(-1, NULL, 0); if(ret>0) { printf("wait success: %d\n",ret); break; } else { printf
("wait filed!\n"); break; } } while(1); } int main() { signal(SIGCHLD,handler); pid_t id=fork(); if(id==0) { printf("i am child - pid : %d\n",getpid); sleep(2); exit(1); } else { while(1) { printf("do father thing\n"
); sleep(1); } } return 0; }

該程式的執行結果如下:
這裡寫圖片描述
說明:父程序fork一個子程序,子程序呼叫exit(2)終止,父程序自定義SIGCHLD訊號處理函式,在handler函式中獲得子程序的退出狀態並列印。
二、不產生殭屍程序的另一種方法
父程序呼叫sigaction函式將SIGCHLD訊號的處理動作設定為SIG_IGN,這樣fork出來的子程序在終止時會自動清理掉,不會產生殭屍程序,也不會通知父程序。
舉例說明:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
int main()
{

    struct sigaction act,oact;
    act.sa_handler=SIG_IGN;
    act.sa_flags=0;
    sigemptyset(&act.sa_mask);
    sigaction(SIGCHLD,&act,&oact);
    pid_t id=fork();
    if(id==0)
    {
        printf("i am child - pid : %d\n",getpid());
        sleep(3);
        exit(1);
    }
    else
    {
        while(1)
        {
        printf("do father thing\n");
        sleep(1);
        }
    }
    return 0;
}

該程式的執行結果如下:
這裡寫圖片描述
說明:系統預設的忽略動作和使用者用sigaction自定義的忽略動作通常是沒有區別的,但是這是一個特例。