網絡編程中wait與waitpid的區別

問題:   

    一個unp中第五章的例子:有5個客戶端幾乎同時向服務器發送終止連接,這時在服務器端將幾乎同時產生SIGCHILD信號,然而信號在內核中是不排隊的,信號處理函數只執行一次(我的理解是5個信號幾乎同時到達,當第一個信號被處理時,其他4個信號是未決的,當信號處理函數處理完第一個到達的信號後,由於沒有產生信號,信號處理函數將不會被再次調用)。那麼在目前情況下,父進程怎樣才能捕獲到所有的子進程的退出狀態呢?

 

分析:

    在SIGCHLD的handler中添加如下代碼顯然不行:

void
sig_chld(int signo)
{
     pid_t   pid;
     int     stat;

     pid = wait(&stat);
     printf("child %d terminated/n", pid);
     return;
}

    因爲使用wait時,它只等到第一個SIGCHLD到達的子進程,之後就如上所示return了。在信號處理函數只能執行一次的前提下,其他4個SIGCHLD信號就沒有被處理。

    而如果在handler中使用如下的方式就可以:

void
sig_chld(int signo)
{
    pid_t   pid;
    int     stat;

    while ( (pid = waitpid(-1, &stat, WNOHANG)) > 0)
        printf("child %d terminated/n", pid);
    return;
}

    原因分析如下:在while循環中使用waitpid的非阻塞模式(WNOHANG),當第一個信號到達時,printf然後回到while繼續waitpid,接着第二個信號到達,依次處理,直到這5個信號都被處理完之後,根據WNOHANG常量的說明“The waitpid function will not block if a child specified by pid is not immediately available. In this case, the return value is 0. ”(見APUE2中8.6節),所以waitpid將返回0,跳出while循環,這樣子進程的終止狀態都被捕獲到了,父進程繼續做它的事。

 

總結:

    wait與waitpid的主要區別:

    (1)waitpid能夠等指定pid的子進程;而wait只能等第一個到達的子進程。

    (2)waitpid通過指定WNOHANG可以不阻塞,沒有可用的子進程就立即返回0;而wait要求父進程一直阻塞。

    上面這兩點其實就是waitpid比wait多了1、3兩個參數。

 

補充:

    查看源碼,wait就是包裝過的waitpid,include/unistd.h

static inline pid_t wait(int * wait_stat)
{
return waitpid(-1,wait_stat,0);
}

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