天天看點

wait和waitpid函數總結

wait和waitpid兩個函數的功能:

1.防止産生僵屍程序             

2.根據需求,先讓父程序挂起等待子程序結束後,再運作,實作程序的同步。

僵屍程序:一個程序使用fork建立子程序,如果子程序退出,而父程序并沒有調用wait或waitpid擷取子程序的狀态資訊,那麼子程序的程序描述符仍然儲存在系統中。這種程序稱之為僵死程序。

如果程序不調用wait / waitpid的話, 那麼保留的那段資訊就不會釋放,其程序号就會一直被占用,但是系統所能使用的程序号是有限的,如果大量的産生僵死程序,将因為沒有可用的程序号而導緻系統不能産生新的程序. 此即為僵屍程序的危害,應當避免。

wait函數:

函數原型:

#include <sys/types.h> 

#include <sys/wait.h>

pid_t wait(int *status)

程序一旦調用了wait,就立即阻塞自己,由wait自動分析是否目前程序的某個子程序已經退出,如果讓它找到了這樣一個已經變成僵屍的子程序,wait就會收集這個子程序的資訊,并把它徹底銷毀後傳回;如果沒有找到這樣一個子程序,wait就會一直阻塞在這裡,直到有一個出現為止。

參數status用來儲存被收集程序退出時的一些狀态,它是一個指向int類型的指針。

參數status:

如果參數status的值不是NULL,wait就會把子程序退出時的狀态取出并存入其中,這是一個整數值(int),指出了子程序是正常退出還是被非正常結束的,以及正常結束時的傳回值,或被哪一個信号結束的等資訊。由于這些資訊被存放在一個整數的不同二進制位中,是以用正常的方法讀取會非常麻煩,人們就設計了一套專門的宏(macro)來完成這項工作:

1.WIFEXITED(status) 這個宏用來指出子程序是否為正常退出的,如果是,它會傳回一個非零值。

2. WEXITSTATUS(status) 當WIFEXITED傳回非零值時,我們可以用這個宏來提取子程序的傳回值,如果子程序調用exit(5)退出,WEXITSTATUS(status) 就會傳回5;如果子程序調用exit(7),WEXITSTATUS(status)就會傳回7。

但如果我們對這個子程序是如何死掉的毫不在意,隻想把這個僵屍程序消滅掉,(事實上絕大多數情況下,我們都會這樣想),我們就可以設定這個參數為NULL,就象下面這樣:

 pid = wait(NULL);

3.WIFSIGNALED(status)若為異常結束子程序傳回的狀态,則為真;對于這種情況可執行WTERMSIG(status),取使子程序結束的信号編号。

4.WTERMSIG(status) 取得子程序因信号而中止的信号代碼,一般會先用 WIFSIGNALED 來判斷後才使用此宏。

5.WIFSTOPPED(status) 若為目前暫停子程序傳回的狀态,則為真;對于這種情況可執行WSTOPSIG(status),取使子程序暫停的信号編号。

6.WSTOPSIG(status) 取得引發子程序暫停的信号代碼,一般會先用 WIFSTOPPED 來判斷後才使用此宏。

如果成功,wait會傳回被收集的子程序的程序ID,如果調用程序沒有子程序,調用就會失敗,此時wait傳回-1,同時errno被置為ECHILD。

waitpid函數:

函數原型:

#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取不同的值時,在這裡有不同的意義。

pid>0時,隻等待程序ID等于pid的子程序,不管其它已經有多少子程序運作結束退出了,隻要指定的子程序還沒有結束,waitpid就會一直等下去。 

pid=-1時,等待任何一個子程序退出,沒有任何限制,此時waitpid和wait的作用一模一樣。

pid=0時,等待同一個程序組中的任何子程序,如果子程序已經加入了别的程序組,waitpid不會對它做任何理睬。 

pid<-1時,等待一個指定程序組中的任何子程序,這個程序組的ID等于pid的絕對值。 

參數options:

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

ret=waitpid(-1,NULL,WNOHANG | WUNTRACED);

如果我們不想使用它們,也可以把options設為0,如:

ret=waitpid(-1,NULL,0);

如果使用了WNOHANG參數調用waitpid,即使沒有子程序退出,它也會立即傳回,不會像wait那樣永遠等下去。

WUNTRACED 若子程序進入暫停狀态,則馬上傳回,但子程序的結束狀态不予以理會。

WCONTINUED //如果停止了的程序由于SIGCONT信号的到來而繼續運作,調用将傳回。

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

當正常傳回的時候,waitpid傳回收集到的子程序的程序ID; 

如果設定了選項WNOHANG,而調用中waitpid發現沒有已退出的子程序可收集,則傳回0; 

如果調用中出錯,則傳回-1,這時errno會被設定成相應的值以訓示錯誤所在;

繼續閱讀