當前位置:
首頁 > 知識 > 子進程的非同步等待方式

子進程的非同步等待方式

我們知道當一個父進程創建一個子進程時,會調用wait和waitpid函數清理僵?進程,?進程可以阻塞等待?進程結束,也可以?阻塞地查詢是否有?進程結束等待清理(也就是輪詢的?式)。采?第?種?式,?進程阻塞了就不 能處理??的?作了;采?第?種?式,?進程在處理??的?作的同時還要記得時不時地輪詢? 下,程序實現複雜。

1.wait和waitpid

(1)wait 函數:用來等待任何一個子進程退出,由父進程調用。

1 #include
2 #include
3 pid_t wait(int* status);

返回值:成功返回被等待子進程的pid,失敗返回-1。 status:輸出型參數,拿回子進程的退出信息。如果參數status不為空,則進程終止狀態被保存於其中。 wait方式:阻塞式等待,等待的子進程不退出時,父進程一直不退出。 目的:回收子進程,系統回收子進程的空間。

依據傳統,返回的整形狀態字是由實現定義的,其中有些位表示退出狀態(正常返回),其他位表示信號編號(異常返回),有一位表示是否產生了一個core文件等。 終止狀態是定義在 sys/wait.h中的各個宏,有四可互斥的宏可以用來取得進程終止的原因。

WIFEXITED:正常返回時為真,可以執行宏函數 WEXITSTATUS獲取子進程傳送給exit、_exit或_Exit的參數的低8位。

WIFSIGNALED:異常返回時為真,可以執行宏函數WTERMSIG取得子進程終止的信號編號,另外,對於一些實現,定義有宏WCOREDUMP宏,若以經昌盛終止進程的core文件,則為真。

WIFSTOPPED:若為當前暫停子進程的返回的狀態,則為真,可執行WSTOPSIG取得使子進程暫停的信號編號。

WIFCONTINUED:若在作業控制暫停後已經繼續的子進程返回了狀態,則為真,僅用於waitpid。

(2)waitpid:

1 #include
2 #include
3 pid_t waitpid(pid_t pid,int* status,int options);

1>參數

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

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

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

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

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

status參數與wait函數的基本相同。

options參數當options參數為0時,與wait功能相同,仍是阻塞式等待,不提供額外功能,如果為下列常量按位或則提供更多功能:

WCONTINUED:若實現支持作業控制,那麼由pid指定的任一子進程在暫停後已經繼續,但狀態尚未報告,則返回狀態

WNOHANG:若由pid指定的子進程並不是立即可用的,則waitpid不阻塞,即此時以非阻塞方式(輪詢式訪問的必要條件)等待子進程,並且返回0。

WUNTRACED:若實現支持作業控制,而pid指定的任一子進程已經暫停,且其狀態尚未報告,則返回其狀態

2>返回值:

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

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

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

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

3>waitpid提供了三個wait所沒有的功能:

1. waitpid可等待一個特定的進程

2. waitpid提供了一個wait的非阻塞版本

3. waitpid支持作業控制

2.關於SIGCHLD信號

其實,?進程在終?時會給?進程發SIGCHLD信號,該信號的默認處理動作是忽略,?進程可以? 定義SIGCHLD信號的處理函數,這樣?進程只需專?處理??的?作,不必關??進程了,?進程 終?時會通知?進程,?進程在信號處理函數中調?wait清理?進程即可。

一般情況下父進程收到這個信號的默認處理是忽略這個信號,即就是不做任何處理,但是我們可以通過系統調用API:signal來進行自定義處理句柄,進行驗證,具體代碼如下:

(1)驗證子進程退出時會給父進程發送SIGCHLD信號

子進程的非同步等待方式

程序完成以下功能:?進程fork出?進程,?進程調?exit(1) 終?,?進程?定義SIGCHLD信號的處理函數,在其中調?wait獲得?進程的退出狀態並列印。

用kill -l指令查看17號信號:

子進程的非同步等待方式

3.子進程的非同步等待方式

(1)非同步回收殭屍進程:

fork之後,非阻塞(非同步)等待子進程(回收殭屍)。

fork之後,子進程和父進程分叉執行,殭屍進程的產生是因為父進程沒有給子進程「收屍」造成的,又可以根據危害程度分為下述兩類:

總體來說:當子進程結束之後,但父進程未結束之前,子進程將成為殭屍進程。

1)當子進程結束之後,但父進程未結束之前,子進程將成為殭屍進程,父進程結束後殭屍被init進程回收。

2)如果子進程結束了,但是父進程始終沒有結束,那麼這個殭屍將一直存在,而且隨著exec,殭屍越來越多。

(2)實現代碼

1 #include
2 #include
3 #include
4 #include
5 #include
6 #include
7 void catchSig(int sig)
8 {
9 printf("father is catching,child is quit
");
10 //以非阻塞方式等待所有異常退出的子進程
11 pid_t id;
12 while((id = waitpid(-1,NULL,WNOHANG)) > 0)
13 {
14 printf("wait child success:%d
",id);
15 }
16 }
17 int main
18 {
19 signal(SIGCHLD,catchSig);
20 pid_t pid1 = fork;
21 if(pid1 == 0)//child1
22 {
23 printf("child1:my pid is %d
",getpid);
24 exit(-1);//子進程1異常終止
25 }
26 pid_t pid2 = fork;//child2
27 if(pid2 == 0)
28 {
29 printf("child2:my pid is %d
",getpid);
30 exit(-1);//子進程2異常退出
31 }
32 pid_t pid3 = fork;//child3
33 if(pid3 == 0)
34 {
35 printf("child3:my pid is %d
",getpid);//子進程3正常運行 
36 }
37 while(1)
38 {
39 printf("father is waiting...
");
40 sleep(1);
41 }
42 return 0;

運行結果:

子進程的非同步等待方式

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 科技優家 的精彩文章:

請教 C 非同步 async await 問題
C簡單構架之EF進行讀寫分離+多資料庫(Mysql/SqlService)
vue 高德地圖之玩轉周邊
在windows下使用Qt5開發GTK3圖形界面應用程序
angular2/angular4 如何通過$http的post方法請求下載二進位的Excel文件

TAG:科技優家 |

您可能感興趣

等待也是善待生命的一種方式
口腔問題要趁早,孩子的牙齒健康經不起賭博式的等待
黃金等待方向性選擇 關注未來通脹走勢
台灣同胞居住證是落實同等待遇的關鍵一步
這種植食性動物的膽子非常大,遇到天敵並不逃跑,反倒在原地等待
在愛情里等待的孩子
稅延養老險進入試點期,產品正式面世尚需等待
獅子運勢強勁 雙子需耐心等待
家長不願等待孩子的三種表現形式
平等待人方是真修行
等待被認領的孩子們
《孫子兵法》——不能等待是巨大的性格缺陷
方丈首次回應李舒克被打:不會心慈手軟,等待警方解決,送進去最好!
愛情真的經不起等待
培養孩子的主動性和解決問題的能力,而不是在考場外等待
網友下班回家,她的貓以這種方式等待她,感動到哭
為了孩子忍受婚姻中各種不平等待遇,真的是為了孩子好嗎?
任正非:獨立組網全球只有華為一家做好,正等待高通進步
看見鏟屎官肚子痛進了廁所,小柴犬乖乖趴門口等待
就是這樣慢熱,在感情中需要對方等待的五大星座