文章試讀
不拘一個遍程序系列:編程序不能一個腦袋鑽到底,有時要學會變通,即所謂的曲線救國。一、二、三、四
職場規劃:一些雜七雜八的職場感悟吧。不值錢的軟件人才 精力充沛與事業成功 讓系分來得更猛烈些吧
我的詩歌:都是我的打油詩,但是很值得一讀。不要工作還衣食無憂之四難歌 香格裡拉美人圖
寶寶圖片:超可愛的小寶寶 寫博客
考試培訓:主要是關於考研、軟考和等級的相關題解。2009考研試題分析 2008年12月程序員試題分析
《精通Unix下C語言編程與項目實踐》之五
僵死進程
作者:朱雲翔,胡平
9.3 僵死進程
僵死進程是已經終止,但沒有從進程表中清除的進程。代碼9-12展示了一個產生僵死進程的例子:
代碼9-12 僵死進程產生模型節自/code/chapter9/szomb1.c)
#include <unistd.h>
#include <stdio.h>
void main()
{
pid_t pid1;
if ((pid1 = fork()) == 0)
{
printf("child[%d]\n", getpid());
exit(0);
}
/* wait(); */ /* ① */
printf("parent[%d]\n", getpid());
sleep(60);
}
編譯代碼9-12:
# make szomb1
cc -O -o szomb1 szomb1.c
後台運行程序szobm1,並在子進程結束後,父進程沒有結束前,運行命令查詢進程情況:
# ./szomb1&
10570
# child[10571]
parent[10570]
# ps -ef|grep 10570
root 10570 10449 0 19:25:50 ttyp0 00:00:00 ./szomb1
root 10571 10570 0 - - 00:00:00 <defunct>
其中“<defunct>”代表僵死進程不同版本Unix描述略有不同)。因此可知,子進程並沒有如期消失,而是轉化為僵死進程繼續占用系統進程表資源。如果系統存在大量的僵死進程,就會過多占用進程表空間,影響新進程的產生。對於僵死進程,不能奢望通過kill命令殺死之,因為它已經“死”了,不再接收任何系統信號。
當子進程終止時,它釋放資源,並且發送SIGCHLD信號通知父進程。父進程接收SIGCHLD信號,調用wait返回子進程的狀態,並且釋放系統進程表資源。故如果子進程先於父進程終止,而父進程沒有調用wait接收子進程信息,則子進程將轉化為僵死進程,直到其父進程結束。
一旦知道了僵死進程的成因,我們就可以采用如下方法預防僵死進程:
1. wait法
父進程主動調用或者接收到SIGC(H)LD信號後調用)wait接收子進程的死亡報告,釋放子進程占用的系統進程表資源。如將代碼9-10中屏蔽的代碼行①“wait();”打開,就可以有效的阻止僵死進程的產生。
2. 托管法
如果父進程先於子進程而死亡,則它的所有子進程轉由進程init領養,即它所有子進程的父進程ID號變為1進程init的標識為1)。當子進程結束時init為其釋放進程表資源。
3. 忽略SIGC(H)LD信號
當父進程忽略SIGC(H)LD信號後,即使不執行wait,子進程結束時也不會產生僵死進程有關信號的相關知識將在下一章講述)。
3. 捕獲SIGC(H)LD信號
當父進程捕獲SIGC(H)LD信號,並在捕獲函數代碼中等待wait)子進程。
實踐經驗】實現托管法的技巧是調用fork兩次,讓子進程退出,子子進程的父進程更改為進程init,這樣父進程就不必理會子子進程的處理了。代碼9-13設計了一個兩次fork避免僵死進程的例子。
代碼9-13 托管法預防僵死進程節自/code/chapter9/szomb2.c)
#include <unistd.h>
#include <stdio.h>
void main()
{
pid_t pid1;
if ((pid1 = fork()) == 0) /* 第一次fork */
{
printf("child[%d]\n", getpid());
if ((pid1 = fork()) == 0) /* 第二次fork */
{
printf("child[%d]\n", getpid());
sleep(20);
exit(0); /* 第二次創建的子進程退出 */
}
exit(0); /* 第一次創建的子進程退出 */
}
waitpid(pid1, 0, 0);
printf("parent[%d]\n", getpid());
sleep(60);
}
編譯代碼9-13:
# make szomb2
cc -O -o szomb2 szomb2.c
後台運行程序szobm2,並在子進程結束前,運行命令查詢進程情況:
# ./szomb2&
10731
# child[10732]
child[10733]
parent[10731]
# ps -ef|grep szomb2
root 10731 10449 0 20:32:19 ttyp0 00:00:00 ./szomb2
root 10733 1 0 20:32:19 ttyp0 00:00:00 ./szomb2
上例中,進程10733的父進程標識號已經更改為1,即已經由系統進程init標識號為1)托管。
相關文章:
封面 前言 目錄 策劃 作者
動態庫 變長參數 文件鎖 外設 僵死進程
本文出自 “編程浪子朱雲翔” 博客,請務必保留此出處http://zhuyunxiang.blog.51cto.com/653596/133246