日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

Wait waitpid

發(fā)布時(shí)間:2023/11/30 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Wait waitpid 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

轉(zhuǎn)自:http://www.cnblogs.com/mickole/p/3187770.html

linux系統(tǒng)編程之進(jìn)程(六):父進(jìn)程查詢子進(jìn)程的退出,wait,waitpid

本節(jié)目標(biāo):

  • 僵進(jìn)程
  • SIGCHLD
  • wait
  • waitpid

一,僵尸進(jìn)程

當(dāng)一個(gè)子進(jìn)程先于父進(jìn)程結(jié)束運(yùn)行時(shí),它與其父進(jìn)程之間的關(guān)聯(lián)還會(huì)保持到父進(jìn)程也正常地結(jié)束運(yùn)行,或者父進(jìn)程調(diào)用了wait才告終止。

子進(jìn)程退出時(shí),內(nèi)核將子進(jìn)程置為僵尸狀態(tài),這個(gè)進(jìn)程稱為僵尸進(jìn)程,它只保留最小的一些內(nèi)核數(shù)據(jù)結(jié)構(gòu),以便父進(jìn)程查詢子進(jìn)程的退出狀態(tài)。

進(jìn)程表中代表子進(jìn)程的數(shù)據(jù)項(xiàng)是不會(huì)立刻釋放的,雖然不再活躍了,可子進(jìn)程還停留在系統(tǒng)里,因?yàn)樗耐顺龃a還需要保存起來以備父進(jìn)程中后續(xù)的wait調(diào)用使用。它將稱為一個(gè)“僵進(jìn)程”。

二,如何避免僵尸進(jìn)程

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

三,SIGCHLD信號(hào)

當(dāng)子進(jìn)程退出的時(shí)候,內(nèi)核會(huì)向父進(jìn)程發(fā)送SIGCHLD信號(hào),子進(jìn)程的退出是個(gè)異步事件(子進(jìn)程可以在父進(jìn)程運(yùn)行的任何時(shí)刻終止)

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

如果將此信號(hào)的處理方式設(shè)為忽略,可讓內(nèi)核把僵尸子進(jìn)程轉(zhuǎn)交給init進(jìn)程去處理,省去了大量僵尸進(jìn)程占用系統(tǒng)資源。

示例:

#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; }

結(jié)果:

可知,雖然子進(jìn)程先退出了,但進(jìn)程表中已經(jīng)不存在子進(jìn)程的僵尸狀態(tài)

?

三,wait()函數(shù)

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

pid_t wait(int *status);

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

pid = wait(NULL);

如果成功,wait會(huì)返回被收集的子進(jìn)程的進(jìn)程ID,如果調(diào)用進(jìn)程沒有子進(jìn)程,調(diào)用就會(huì)失敗,此時(shí)wait返回-1,同時(shí)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系統(tǒng)調(diào)用會(huì)使父進(jìn)程暫停執(zhí)行,直到它的一個(gè)子進(jìn)程結(jié)束為止。
  • 返回的是子進(jìn)程的PID,它通常是結(jié)束的子進(jìn)程
  • 狀態(tài)信息允許父進(jìn)程判定子進(jìn)程的退出狀態(tài),即從子進(jìn)程的main函數(shù)返回的值或子進(jìn)程中exit語句的退出碼。
  • 如果status不是一個(gè)空指針,狀態(tài)信息將被寫入它指向的位置

可以上述的一些宏判斷子進(jìn)程的退出情況:

示例程序:

#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; }

結(jié)果:

當(dāng)子進(jìn)程正常退出時(shí)wait返回子進(jìn)程pid,且WIFEXITED(status)驗(yàn)證為真,可以WEXITSTATUS(status)獲得返回狀態(tài)碼

示例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; }

結(jié)果:

當(dāng)子進(jìn)程異常退出時(shí),WIFSIGNALED(status)為真,可用WTERMSIG(status)獲得信號(hào)

?

四,waitpid()函數(shù)

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

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

參數(shù):

status:如果不是空,會(huì)把狀態(tài)信息寫到它指向的位置,與wait一樣

options:允許改變waitpid的行為,最有用的一個(gè)選項(xiàng)是WNOHANG,它的作用是防止waitpid把調(diào)用者的執(zhí)行掛起

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.

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

對(duì)于waitpid的p i d參數(shù)的解釋與其值有關(guān):

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

pid > 0 等待其進(jìn)程I D與p i d相等的子進(jìn)程。

pid == 0 等待其組I D等于調(diào)用進(jìn)程的組I D的任一子進(jìn)程。換句話說是與調(diào)用者進(jìn)程同在一個(gè)組的進(jìn)程。

pid < -1 等待其組I D等于p i d的絕對(duì)值的任一子進(jìn)程

wait與waitpid區(qū)別:

  • 在一個(gè)子進(jìn)程終止前, wait 使其調(diào)用者阻塞,而waitpid 有一選擇項(xiàng),可使調(diào)用者不阻塞。
  • waitpid并不等待第一個(gè)終止的子進(jìn)程—它有若干個(gè)選擇項(xiàng),可以控制它所等待的特定進(jìn)程。
  • 實(shí)際上wait函數(shù)是waitpid函數(shù)的一個(gè)特例。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; }

結(jié)果:

可知,option設(shè)為WNOHANG,父進(jìn)程不會(huì)等到子進(jìn)程的退出,即不會(huì)阻塞,如果沒有子進(jìn)程退出則立即返回-1,


總結(jié)

以上是生活随笔為你收集整理的Wait waitpid的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。