Wait waitpid

轉自:http://www.cnblogs.com/mickole/p/3187770.html

linux系統編程之進程(六):父進程查詢子進程的退出,wait,waitpid

本節目標:

  • 僵進程
  • SIGCHLD
  • wait
  • waitpid

一,僵尸進程

當一個子進程先于父進程結束運行時,它與其父進程之間的關聯還會保持到父進程也正常地結束運行,或者父進程調用了wait才告終止。

子進程退出時,內核將子進程置為僵尸狀態,這個進程稱為僵尸進程,它只保留最小的一些內核數據結構,以便父進程查詢子進程的退出狀態。

進程表中代表子進程的數據項是不會立刻釋放的,雖然不再活躍了,可子進程還停留在系統里,因為它的退出碼還需要保存起來以備父進程中后續的wait調用使用。它將稱為一個“僵進程”。

二,如何避免僵尸進程

  • 調用wait或者waitpid函數查詢子進程退出狀態,此方法父進程會被掛起。
  • 如果不想讓父進程掛起,可以在父進程中加入一條語句:signal(SIGCHLD,SIG_IGN);表示父進程忽略SIGCHLD信號,該信號是子進程退出的時候向父進程發送的。

三,SIGCHLD信號

當子進程退出的時候,內核會向父進程發送SIGCHLD信號,子進程的退出是個異步事件(子進程可以在父進程運行的任何時刻終止)

如果不想讓子進程編程僵尸進程可在父進程中加入:signal(SIGCHLD,SIG_IGN);

如果將此信號的處理方式設為忽略,可讓內核把僵尸子進程轉交給init進程去處理,省去了大量僵尸進程占用系統資源。

示例:

復制代碼
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>int main(void)
{pid_t pid;if(signal(SIGCHLD,SIG_IGN) == SIG_ERR){perror("signal error");exit(EXIT_FAILURE);}pid = fork();if(pid == -1){perror("fork error");exit(EXIT_FAILURE);}if(pid == 0){printf("this is child process\n");exit(0);}if(pid > 0){sleep(100);printf("this is parent process\n");}return 0;
}
復制代碼

結果:

QQ截圖20130713104153

可知,雖然子進程先退出了,但進程表中已經不存在子進程的僵尸狀態

?

三,wait()函數

#include <sys/types.h>?
#include <sys/wait.h>

pid_t wait(int *status);

進程一旦調用了wait,就立即阻塞自己,由wait自動分析是否當前進程的某個子進程已經退出,如果讓它找到了這樣一個已經變成僵尸的子進程,wait就會收集這個子進程的信息,并把它徹底銷毀后返回;如果沒有找到這樣一個子進程,wait就會一直阻塞在這里,直到有一個出現為止。?
參數status用來保存被收集進程退出時的一些狀態,它是一個指向int類型的指針。但如果我們對這個子進程是如何死掉的毫不在意,只想把這個僵尸進程消滅掉,(事實上絕大多數情況下,我們都會這樣想),我們就可以設定這個參數為NULL,就象下面這樣:

		pid = wait(NULL);

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

man幫助:

DESCRIPTION?
?????? All of these system calls are used to wait for state changes in a child?
?????? of the calling process, and obtain information about? the? child? whose?
?????? state? has changed.? A state change is considered to be: the child ter-?
?????? minated; the child was stopped by a signal; or the child was resumed by?
?????? a? signal.? In the case of a terminated child, performing a wait allows?
?????? the system to release the resources associated with? the? child;? if? a?
?????? wait? is not performed, then the terminated child remains in a "zombie"?
?????? state (see NOTES below).

?????? If a child has already changed state, then these calls? return? immedi-?
?????? ately.?? Otherwise? they? block until either a child changes state or a?
?????? signal handler interrupts the call (assuming that system calls are? not?
?????? automatically restarted using the SA_RESTART flag of sigaction(2)).? In?
?????? the remainder of this page, a child whose state has changed? and? which?
?????? has? not? yet? been? waited upon by one of these system calls is termed?
?????? waitable.?

wait() :?
??? The wait() system call suspends execution of the calling process? until?
??? one? of? its children terminates.? The call wait(&status) is equivalent?
??? to:

??????? waitpid(-1, &status, 0);

If status is not NULL, wait() and waitpid() store status information in?
????? the? int? to? which? it points.? This integer can be inspected with the?
????? following macros (which take the integer itself as an argument,? not? a?
????? pointer to it, as is done in wait() and waitpid()!):

????? WIFEXITED(status)?
???????????? returns true if the child terminated normally, that is, by call-?
???????????? ing exit(3) or _exit(2), or by returning from main().

????? WEXITSTATUS(status)?
???????????? returns the exit status of the? child.?? This? consists? of? the?
???????????? least? significant? 8 bits of the status argument that the child?
???????????? specified in a call to exit(3) or _exit(2) or? as? the? argument?
???????????? for? a? return? statement? in main().? This macro should only be?
???????????? employed if WIFEXITED returned true.

????? WIFSIGNALED(status)?
???????????? returns true if the child process was terminated by a signal.

??? WTERMSIG(status)?
???????????? returns the number of the signal that caused the? child? process?
???????????? to terminate.? This macro should only be employed if WIFSIGNALED?
???????????? returned true.

????? WCOREDUMP(status)?
???????????? returns true if the child produced? a? core? dump.?? This? macro?
???????????? should? only? be? employed? if? WIFSIGNALED returned true.? This?
???????????? macro is not specified in POSIX.1-2001 and is not? available? on?
???????????? some? Unix? implementations? (e.g.,? AIX, SunOS).? Only use this?
???????????? enclosed in #ifdef WCOREDUMP ... #endif.

????? WIFSTOPPED(status)?
???????????? returns true if the child process was stopped by delivery? of? a?
???????????? signal;? this? is? only possible if the call was done using WUN-?
???????????? TRACED or when the child is being traced (see ptrace(2)).

????? WSTOPSIG(status)?
???????????? returns the number of the signal which caused the child to stop.?
???????????? This? macro should only be employed if WIFSTOPPED returned true.


?? WIFCONTINUED(status)?
?????? (since Linux 2.6.10) returns? true? if? the? child? process? was?
?????? resumed by delivery of SIGCONT.

  • wait系統調用會使父進程暫停執行,直到它的一個子進程結束為止。
  • 返回的是子進程的PID,它通常是結束的子進程
  • 狀態信息允許父進程判定子進程的退出狀態,即從子進程的main函數返回的值或子進程中exit語句的退出碼。
  • 如果status不是一個空指針,狀態信息將被寫入它指向的位置

可以上述的一些宏判斷子進程的退出情況:

QQ截圖20130713110230

示例程序:

復制代碼
#include <stdio.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <unistd.h>int main(void)
{pid_t pid;pid = fork();if(pid < 0){perror("fork error");exit(EXIT_FAILURE);}if(pid == 0){printf("this is child process\n");exit(100);}int status;pid_t ret;ret = wait(&status);if(ret <0){perror("wait error");exit(EXIT_FAILURE);}printf("ret = %d pid = %d\n", ret, pid);if (WIFEXITED(status))printf("child exited normal exit status=%d\n", WEXITSTATUS(status));else if (WIFSIGNALED(status))printf("child exited abnormal signal number=%d\n", WTERMSIG(status));else if (WIFSTOPPED(status))printf("child stoped signal number=%d\n", WSTOPSIG(status));return 0;
}
復制代碼

結果:

QQ截圖20130713111249

當子進程正常退出時wait返回子進程pid,且WIFEXITED(status)驗證為真,可以WEXITSTATUS(status)獲得返回狀態碼

示例2:

復制代碼
#include <stdio.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <unistd.h>int main(void)
{pid_t pid;pid = fork();if(pid < 0){perror("fork error");exit(EXIT_FAILURE);}if(pid == 0){printf("this is child process\n");//exit(100);
        abort();}int status;pid_t ret;ret = wait(&status);if(ret <0){perror("wait error");exit(EXIT_FAILURE);}printf("ret = %d pid = %d\n", ret, pid);if (WIFEXITED(status))printf("child exited normal exit status=%d\n", WEXITSTATUS(status));else if (WIFSIGNALED(status))printf("child exited abnormal signal number=%d\n", WTERMSIG(status));else if (WIFSTOPPED(status))printf("child stoped signal number=%d\n", WSTOPSIG(status));return 0;
}
復制代碼

結果:

QQ截圖20130713111642

當子進程異常退出時,WIFSIGNALED(status)為真,可用WTERMSIG(status)獲得信號

?

四,waitpid()函數

#include <sys/types.h>?
#include <sys/wait.h>

pid_t waitpid(pid_t pid, int *status, int options);

參數:

status:如果不是空,會把狀態信息寫到它指向的位置,與wait一樣

options:允許改變waitpid的行為,最有用的一個選項是WNOHANG,它的作用是防止waitpid把調用者的執行掛起

The value of options is an OR of zero or more? of? the? following? con-?
stants:

WNOHANG???? return immediately if no child has exited.

WUNTRACED?? also? return? if? a? child? has stopped (but not traced via?
??????????? ptrace(2)).? Status for traced children which have? stopped?
??????????? is provided even if this option is not specified.

WCONTINUED (since Linux 2.6.10)?
??????????? also return if a stopped child has been resumed by delivery?
??????????? of SIGCONT.

返回值:如果成功返回等待子進程的ID,失敗返回-1

對于waitpid的p i d參數的解釋與其值有關:

pid == -1 等待任一子進程。于是在這一功能方面waitpid與wait等效。

pid > 0 等待其進程I D與p i d相等的子進程。

pid == 0 等待其組I D等于調用進程的組I D的任一子進程。換句話說是與調用者進程同在一個組的進程。

pid < -1 等待其組I D等于p i d的絕對值的任一子進程

wait與waitpid區別:

  • 在一個子進程終止前, wait 使其調用者阻塞,而waitpid 有一選擇項,可使調用者不阻塞。
  • waitpid并不等待第一個終止的子進程—它有若干個選擇項,可以控制它所等待的特定進程。
  • 實際上wait函數是waitpid函數的一個特例。waitpid(-1, &status, 0);

示例:

復制代碼
#include <stdio.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <unistd.h>int main(void)
{pid_t pid;pid = fork();if(pid < 0){perror("fork error");exit(EXIT_FAILURE);}if(pid == 0){printf("this is child process\n");sleep(5);exit(100);}int status;pid_t ret;ret = waitpid(pid,&status,WNOHANG);if(ret <0){perror("wait error");exit(EXIT_FAILURE);}printf("ret = %d pid = %d\n", ret, pid);if (WIFEXITED(status))printf("child exited normal exit status=%d\n", WEXITSTATUS(status));else if (WIFSIGNALED(status))printf("child exited abnormal signal number=%d\n", WTERMSIG(status));else if (WIFSTOPPED(status))printf("child stoped signal number=%d\n", WSTOPSIG(status));return 0;
}
復制代碼

結果:

QQ截圖20130713112838

可知,option設為WNOHANG,父進程不會等到子進程的退出,即不會阻塞,如果沒有子進程退出則立即返回-1,


本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/384409.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/384409.shtml
英文地址,請注明出處:http://en.pswp.cn/news/384409.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Linux系統編程(五)時序競態

時序競態產生原因改進總結產生原因 #include <cstdio> #include <stdio.h> #include <sys/time.h> #include <unistd.h> #include <signal.h> #include <stdlib.h> #include <errno.h>void catch_sigalrm(int signo) {printf("…

Linux C++ 簡單爬蟲

轉載&#xff1a;http://blog.csdn.net/orthocenterchocolate/article/details/38665937 方便易用&#xff0c;傳入URL&#xff0c;返回對應頁面的內容 [cpp] view plaincopy #include <iostream> #include <string> #include <netdb.h> #include <…

Linux系統編程(六)守護進程

Linux系統編程&#xff08;六&#xff09;守護進程一、進程組概念二、會話創建會話的條件守護進程概念守護進程模型創建守護進程一、進程組 概念 進程組&#xff0c;也稱之為作業。代表一個或多個進程的集合。每個進程都屬于一個進程組。 當父進程&#xff0c;創建子進程的時…

TCP 客戶端和服務器端

轉自&#xff1a;http://blog.csdn.net/itcastcpp/article/details/39047265 前面幾篇中實現的client每次運行只能從命令行讀取一個字符串發給服務器&#xff0c;再從服務器收回來&#xff0c;現在我們把它改成交互式的&#xff0c;不斷從終端接受用戶輸入并和server交互。 [cp…

利用多線程實現linux下C語言的聊天室程序:

轉載&#xff1a;http://www.360doc.com/content/16/0421/11/478627_552531090.shtml 利用多線程實現linux下C語言的聊天室程序&#xff1a; 客戶端代碼&#xff1a; threadsend線程負責客戶端消息的發送&#xff1b; threadrecv線程負責客戶端接受服務器端的消息。 [html] v…

Linux系統編程(七)消息隊列

Linux系統編程&#xff08;七&#xff09;消息隊列一、什么是消息隊列二、消息隊列內部原理三、實現消息隊列的收發1.發送消息隊列2.接收消息隊列四、消息隊列與命名管道的比較一、什么是消息隊列 消息隊列提供了一種從一個進程向另一個進程發送一個數據塊的方法。每個數據塊都…

基于Linux的SOCKET編程之TCP半雙工Client-Server聊天程序

轉自&#xff1a;http://blog.csdn.net/apollon_krj/article/details/53398448#0-tsina-1-64987-397232819ff9a47a7b7e80a40613cfe1 所謂半雙工通信&#xff0c;即通信雙方都可以實現接發數據&#xff0c;但是有一個限制&#xff1a;只能一方發一方收&#xff0c;之后交換收發對…

Linux系統編程(八)線程

Linux系統編程&#xff08;八&#xff09;線程一、什么是線程&#xff1f;二、Linux內核線程實現原理線程共享資源線程非共享資源線程優缺點線程控制原語一、什么是線程&#xff1f; LWP&#xff1a;light weight process 輕量級的進程&#xff0c;本質仍是進程(在Linux環境下…

智能算法(GA、DBO等)求解阻塞流水車間調度問題(BFSP)

先做一個聲明&#xff1a;文章是由我的個人公眾號中的推送直接復制粘貼而來&#xff0c;因此對智能優化算法感興趣的朋友&#xff0c;可關注我的個人公眾號&#xff1a;啟發式算法討論。我會不定期在公眾號里分享不同的智能優化算法&#xff0c;經典的&#xff0c;或者是近幾年…

Linux socket編程,對套接字進行封裝

轉自&#xff1a;http://www.cnblogs.com/-Lei/archive/2012/09/04/2670942.html 下面是對socket操作的封裝&#xff0c;因為在Linux下寫中文到了windows里面會亂碼&#xff0c;所以注釋用英文來寫&#xff0c;有空再查下解決方法吧 socket.h #ifndef SOCKET_H #define SOCKET_…

Linux系統編程(九)線程同步

Linux系統編程&#xff08;九&#xff09;線程同步一、什么是線程同步&#xff1f;二、互斥量三、條件變量pthread_cond_wait函數pthread_cond_signal函數生產者和消費者模型一、什么是線程同步&#xff1f; 線程同步&#xff0c;指一個線程發出某一功能調用時&#xff0c;在沒…

linux網絡編程(一)網絡基礎傳輸知識

linux網絡編程&#xff08;一&#xff09;網絡傳輸基礎知識一、什么是協議&#xff1f;二、使用步驟典型協議2.網絡應用程序設計模式C/S模式B/S模式優缺點3.分層模型4.TCP/IP四層模型通信過程5.協議格式數據包封裝以太網幀格式ARP數據報格式IP段格式UDP數據報格式TCP數據報格式…

linux網絡編程:使用多進程實現socket同時收發數據

轉載&#xff1a;http://blog.csdn.net/li_wen01/article/details/52685844 前面已講過使用一個進程實現服務端和客戶端P2P通信的實例&#xff0c;但是它只能同時處理一個客戶端的連接。如果要實現并發處理多個客戶端的連接并且實現P2P通信&#xff0c;可以使用多進程來處理。相…

Linux 進程學習(四)------ sigaction 函數

轉自&#xff1a;http://www.cnblogs.com/wblyuyang/archive/2012/11/13/2768923.html 使用 sigaction 函數&#xff1a; signal 函數的使用方法簡單&#xff0c;但并不屬于 POSIX 標準&#xff0c;在各類 UNIX 平臺上的實現不盡相同&#xff0c;因此其用途受 到了一定的限制…

linux網絡編程(二)高并發服務器

linux網絡編程&#xff08;二&#xff09;高并發服務器錯誤處理高并發服務器多進程并發服務器客戶端錯誤處理 #include "wrap.h"int Bind(int fd, const struct sockaddr* sa, socklen_t salen) {int ret;if ((ret bind(fd, sa, salen)) < 0){perror("bind…

linux知識(一) 程序、進程與線程

linux知識&#xff08;一&#xff09; 程序、進程與線程程序進程程序如何變成進程&#xff1f;線程線程與進程fork和創建新線程的區別優點程序 程序&#xff1a;程序是已編譯好的二進制文件&#xff0c;存儲在磁盤中&#xff0c;不占用系統資源 程序包括&#xff1a; RO段&am…

linux 信號signal和sigaction理解

轉載&#xff1a;http://blog.csdn.net/beginning1126/article/details/8680757 今天看到unp時發現之前對signal到理解實在淺顯&#xff0c;今天拿來單獨學習討論下。 signal&#xff0c;此函數相對簡單一些&#xff0c;給定一個信號&#xff0c;給出信號處理函數則可&#xff…

linux知識(二)互斥量、信號量和生產者消費者模型

linux知識&#xff08;二&#xff09;互斥量、信號量和生產者消費者模型一、互斥量產生原因二、信號量生產者消費者模型一、互斥量 產生原因 使用多線程常常會碰到數據混亂的問題&#xff0c;那么使用互斥量&#xff0c;相當于“加鎖”的操作&#xff0c;將有助于解決數據混亂…

基于Linux的Socket編程之TCP全雙工Server-Client聊天程序

轉載&#xff1a;http://blog.csdn.net/apollon_krj/article/details/53437764#0-tsina-1-58570-397232819ff9a47a7b7e80a40613cfe1 一、引言&#xff1a; 由于accept函數、read、write、recv、send等函數都是是阻塞式的&#xff0c;在同一個進程之中&#xff0c;只要有任何一個…

數據結構(一)線性表

數據結構&#xff08;一&#xff09;線性表一、線性表定義二、順序表定義動態數組三、單鏈表定義不帶頭結點帶頭結點頭結點與不帶頭結點的區別頭插法與尾插法雙鏈表循環鏈表循環單鏈表循環雙鏈表靜態鏈表一、線性表定義 線性表是具有相同數據類型的n個數據元素的有限序列 特點…