Linux系統調用--------wait() 與 waitpid()

waitpid系統調用在Linux函數庫中的原型是:
#include <sys/types.h> 
#include <sys/wait.h>
pid_t waitpid(pid_t pid,int *status,int options)
從本質上講,系統調用waitpid和wait的作用是完全相同的,但waitpid多出了兩個可由用戶控制的參數pid和options,從而爲我們編程提供了另一種更靈活的方式。下面我們就來詳細介紹一下這兩個參數:

 

pid

從參數的名字pid和類型pid_t中就可以看出,這裏需要的是一個進程ID。但當pid取不同的值時,在這裏有不同的意義。

  1. pid>0時,只等待進程ID等於pid的子進程,不管其它已經有多少子進程運行結束退出了,只要指定的子進程還沒有結束,waitpid就會一直等下去。
  2. pid=-1時,等待任何一個子進程退出,沒有任何限制,此時waitpid和wait的作用一模一樣。
  3. pid=0時,等待同一個進程組中的任何子進程,如果子進程已經加入了別的進程組,waitpid不會對它做任何理睬。
  4. pid<-1時,等待一個指定進程組中的任何子進程,這個進程組的ID等於pid的絕對值。

options

options提供了一些額外的選項來控制waitpid,目前在Linux中只支持WNOHANG和WUNTRACED兩個選項,這是兩個常數,可以用"|"運算符把它們連接起來使用,比如:

ret=waitpid(-1,NULL,WNOHANG | WUNTRACED);
如果我們不想使用它們,也可以把options設爲0,如:
ret=waitpid(-1,NULL,0);
如果使用了WNOHANG(wait no hung)參數調用waitpid,即使沒有子進程退出,它也會立即返回,不會像wait那樣永遠等下去。

而WUNTRACED參數,由於涉及到一些跟蹤調試方面的知識,加之極少用到,這裏就不多費筆墨了,有興趣的讀者可以自行查閱相關材料。

   

 wait不就是經過包裝的waitpid嗎?沒錯,察看<內核源碼目錄>/include/unistd.h文件349-352行就會發現以下程序段:

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

1.9.2 返回值和錯誤

waitpid的返回值比wait稍微複雜一些,一共有3種情況:

  1. 當正常返回的時候,waitpid返回收集到的子進程的進程ID;
  2. 如果設置了選項WNOHANG,而調用中waitpid發現沒有已退出的子進程可收集,則返回0;
  3. 如果調用中出錯,則返回-1,這時errno會被設置成相應的值以指示錯誤所在;

當pid所指示的子進程不存在,或此進程存在,但不是調用進程的子進程,waitpid就會出錯返回,這時errno被設置爲ECHILD;

#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
main()
{
    pid_t pc, pr; 
    pc=fork();
    if(pc<0)  
    printf("Error occured on forking.\n");
    else if(pc==0)
    {  
    sleep(4); 
    exit(0);
    }
    
    do
    {
    pr=waitpid(pc, NULL, WNOHANG); 
     if(pr==0)
     {   
      printf("No child exited\n");
      sleep(1);
     }
    }while(pr==0);    
    if(pr==pc)
     printf("successfully release child %d\n", pr);
    else
     printf("some error occured\n");
}

編譯並運行:

$ cc waitpid.c -o waitpid
$ ./waitpid
No child exited
No child exited
No child exited
No child exited
successfully release child 1526

父進程經過4次失敗的嘗試之後,終於收集到了退出的子進程。

因爲這只是一個例子程序,不便寫得太複雜,所以我們就讓父進程和子進程分別睡眠了4秒鐘和1秒鐘,代表它們分別作了4秒鐘和1秒鐘的工作。父子進程都有工作要做,父進程利用工作的簡短間歇察看子進程的是否退出,如退出就收集它.這樣的話,既不影響父進程的工作,也可以消除殭屍進程.

最後 不管是 wait 還是waitpid函數都有個參數來反映子進程的結束狀態,底下有幾個宏可判別結束情況,參數當然是指針指向的那個:


WIFEXITED(status)如果子進程正常結束則爲非0 值。

WEXITSTATUS(status)取得子進程exit()返回的結束代碼,一般會先用WIFEXITED 來判斷是否正常結束才能使用此宏。


WIFSIGNALED(status)如果子進程是因爲信號而結束則此宏值爲真
WTERMSIG(status) 取得子進程因信號而中止的信號代碼,一般會先用WIFSIGNALED 來判斷後才使用此宏。


WIFSTOPPED(status) 如果子進程處於暫停執行情況則此宏值爲真。一般只有使用WUNTRACED 時纔會有此情況。
WSTOPSIG(status) 取得引發子進程暫停的信號代碼,一般會先用WIFSTOPPED 來判斷後才使用此宏。


返回值
如果執行成功則返回子進程識別碼(PID),如果有錯誤發生則返回

-1。失敗原因存於errno 中。


轉自:http://blog.sina.com.cn/s/blog_602a39250100xfxx.html

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