轉載請注明:http://www.coder4.com/index.php
/archives/151
首先特別感謝這篇文章給的啟發!
http://hi.baidu.com/%D3%EA%BA%E7%D1%F4/blog/item/6490202aaba49193023bf633.html
對原作者表示敬意和膜拜!
fork()之后,非阻塞(異步)等待子進程(回收僵尸)。
fork()之后,子進程和父進程分叉執行,僵尸進程的產生是因為父進程沒有給子進程“收尸”造成的,又可以根據危害程度分為下述兩類:
總體來說:當子進程結束之后,但父進程未結束之前,子進程將成為僵尸進程。
(1)當子進程結束之后,但父進程未結束之前,子進程將成為僵尸進程,父進程結束后僵尸被init進程回收。
(2)如果子進程結束了,但是父進程始終沒有結束,那么這個僵尸將一直存在,而且隨著exec,僵尸越來越多。
如下面的代碼,在父進程執行的5s內,子進程將為僵尸:
25 |
printf ( "The child process is %d\n" , c_pid); |
30 |
printf ( "I 'm a child.\n" ); |
如上面的代碼,在父進程的5s內,子進程一直是僵尸!
因此,需要對僵尸進程進行回收,傳統的回收方法是,使用wait()函數,等待子進程,wait()是阻塞模式的,當子進程沒有結束之前,wait一直等
待,不往下面的語句執行。
26 |
printf ( "The child process is %d\n" , c_pid); |
29 |
if ((pid =
wait(&status)) != -1 && pid == c_pid) { |
31 |
printf ( "The child exit with %d\n" , WEXITSTATUS(status)); |
34 |
printf ( "wait() fail.\n" ); |
36 |
printf ( "Now , The child has
been exit , and I will sleep.\n" ); |
41 |
printf ( "I 'm a child.\n" ); |
轉載自:4號程序員
如上面的代碼,在子進程執行5秒后,即被回收,在夫進程的20秒內,子進程已經被結束,不再是僵尸。
但是這種利用wait()阻塞等待的方法也有一定的缺陷,那就是父進程必須等待子進程,無法做其他事情,如何非阻塞的等待子進程呢?
man wait,查看NOTES章節,可以找到:
子進程退出的時候,會發送SIGCHLD信號,默認的POSIX不響應,所以,我們只需要把處理SIGCHLD的函數自己實現就OK了,怎么作呢?
signal用于設置處理信號量的規則(或跳轉到的函數)
1 |
signal (SIGCHLD,handler); |
6 |
int pid =
waitpid(-1,&status,WNOHANG); |
9 |
printf ( "The child exit with code %d" ,WEXITSTATUS(status)); |
OK,全部代碼如下,注意父進程不要再用wait阻塞啦!
18 |
void handler( int num) { |
21 |
int pid = waitpid(-1, &status,
WNOHANG); |
22 |
if (WIFEXITED(status)) { |
23 |
printf ( "The child %d exit with code %d\n" , pid, WEXITSTATUS(status)); |
32 |
signal (SIGCHLD, handler); |
37 |
printf ( "The child process is %d\n" , c_pid); |
40 |
for ( int i = 0; i < 10; i++) { |
41 |
printf ( "Do parent things.\n" ); |
48 |
printf ( "I 'm a child.\n" ); |
posted on 2010-03-30 11:27
chatler 閱讀(388)
評論(0) 編輯 收藏 引用 所屬分類:
Linux_Coding