子進程異步等待方式

1. 原理

1、子進程在退出時,會給父進程發送17號信號 SIGCHLD
2、可以對信號SIGCHLD進行自定義動作,執行handler
3、handler是系統回調函數,在收到該信號後,在進程又內核返回用戶態前,處理自定義函數handler。

2、異步等待子進程

void handler(int sig)
{
    pid_t ret = waitpid(-1,NULL,WNOHANG);
    printf("get a sig:%d\n",sig);
    printf("wait a id: %d\n",ret);
}
int main()
{
    signal(SIGCHLD, handler);
    pid_t id = fork();
    if(id < 0)
        perror("fork");
    else if(id == 0){//child
        printf("i am child: %d\n",getpid());
        sleep(4);
        printf("id: %d child quit! \n",getpid());
        exit(1);
    }
    else{//father
        while(1){
            sleep(1);
            printf("i am father:%d\n",getpid());
        }
    }
    return 0;
}

這裏寫圖片描述
我們可以看到,已經實現了單個子進程異步等待的方式,但當我們多個進程退出時,不知道這個代碼還可以嗎??

void handler(int sig)
{
    pid_t ret = waitpid(-1,NULL,WNOHANG);
    printf("get a sig:%d\n",sig);
    printf("wait a id: %d\n",ret);
}
int main()
{
    signal(SIGCHLD, handler);
    pid_t id = fork();
    if(id < 0)
        perror("fork");
    else if(id == 0)
    {//child
        printf("i am child 1: %d\n",getpid());
        sleep(2);
        printf("id: %d child quit! \n",getpid());
        exit(1);
    }
    else
    {//father
        if(fork() == 0){//再創建了一個子進程
            printf("i am child 2: %d\n",getpid());
            sleep(5);
            printf("id: %d child quit! \n",getpid());
            exit(2);
        }
        while(1){
            sleep(1);
            printf("i am father:%d\n",getpid());
        }
    }
    return 0;
}

這裏寫圖片描述
看到上面的結果,貌似已經實現了可以等待多個子進程,其實不然,如果出現了:在進程從內核返回用戶態前有多個子進程退出了,而系統只會調用handler一次。
如果我們把讓代碼的兩個子進程的sleep時間都寫成4秒結果就有變成了:
這裏寫圖片描述
要處理這種情況,我們只需要加入循環:(更改handler代碼):

void handler(int sig)
{
    printf("get a sig:%d\n",sig);
    pid_t ret;
    do{
        ret = waitpid(-1,NULL,WNOHANG);
        if(ret > 0){
            printf("wait a id: %d\n",ret);
        }
    }while(ret > 0);
}

這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章