淺談僵尸進(jìn)程與孤兒進(jìn)程

在《unix環(huán)境高級(jí)編程》中有提到僵尸進(jìn)程孤兒進(jìn)程。不少同學(xué)對(duì)這兩個(gè)概念會(huì)混淆,這篇文章總結(jié)一下。

在 unix/linux 系統(tǒng)中狂秘,大多情況下,子進(jìn)程是通過(guò)父進(jìn)程 fork 創(chuàng)建的躯肌,注:系統(tǒng)調(diào)用 fork者春,是一個(gè)比較有意思系統(tǒng)調(diào)用,它調(diào)用一次清女,返回兩個(gè)值钱烟,失敗返回 -1,成功時(shí)在子進(jìn)程返回 0,父進(jìn)程返回所創(chuàng)建子進(jìn)程的 pid。

子進(jìn)程創(chuàng)建后拴袭,子進(jìn)程的結(jié)束和父進(jìn)程的運(yùn)行是一個(gè)異步過(guò)程,也就是說(shuō)父進(jìn)程沒(méi)辦法預(yù)測(cè)子進(jìn)程什么時(shí)候結(jié)束读第。 當(dāng)一個(gè)子進(jìn)程完成它的工作終止之后,其父進(jìn)程需要調(diào)用 wait() 或 waitpid() 去獲取子進(jìn)程的終止?fàn)顟B(tài)拥刻。

孤兒進(jìn)程

所謂孤兒進(jìn)程怜瞒,顧名思義,和現(xiàn)實(shí)生活中的孤兒有點(diǎn)類似般哼,當(dāng)一個(gè)進(jìn)程的父進(jìn)程結(jié)束時(shí)吴汪,但是它自己還沒(méi)有結(jié)束,那么這個(gè)進(jìn)程將會(huì)成為孤兒進(jìn)程蒸眠。最后孤兒進(jìn)程將會(huì)被 init 進(jìn)程(進(jìn)程號(hào)為1)的進(jìn)程收養(yǎng)漾橙,當(dāng)然在子進(jìn)程結(jié)束時(shí)也會(huì)由 init 進(jìn)程完成對(duì)它的狀態(tài)收集工作,因此一般來(lái)說(shuō)黔宛,孤兒進(jìn)程并不會(huì)有什么危害近刘。

下面看一個(gè)關(guān)于孤兒進(jìn)程的例子:先打印父進(jìn)程 id擒贸,然后創(chuàng)建子進(jìn)程臀晃,讓父進(jìn)程睡眠 5s,讓子進(jìn)程先運(yùn)行循環(huán)打印出其進(jìn)程 id(pid)介劫;隨后子進(jìn)程睡眠 1-3s(此運(yùn)行過(guò)程父進(jìn)程會(huì)結(jié)束)徽惋,目的是讓父進(jìn)程先于子進(jìn)程結(jié)束,讓子進(jìn)程有個(gè)孤兒的狀態(tài)座韵;最后子進(jìn)程再打印出其進(jìn)程 id(pid) 以及父進(jìn)程 id(ppid) 险绘;觀察兩次打印 其父進(jìn)程 id(ppid) 的區(qū)別。

示例代碼:

<?php
// 獲取當(dāng)前進(jìn)程ID
$parentPid = posix_getpid();
echo "parent progress pid:{$parentPid}\n";

$childList = array();

// 創(chuàng)建子進(jìn)程
$pid = pcntl_fork();
if ( $pid == -1) {
    // 創(chuàng)建失敗
    exit("fork progress error!\n");
} else if ($pid == 0) {
    $repeatNum = 10;
    for ( $i = 1; $i <= $repeatNum; $i++) {
        // 子進(jìn)程執(zhí)行程序
        $ppid = posix_getppid();
        $pid = posix_getpid();

        echo "PPID:{$ppid} , PID:{$pid} child progress is running! {$i} \n";
        $rand = rand(1,3);
        sleep($rand);
    }
    exit("({$pid})child progress end!\n");
} else {
    // 父進(jìn)程執(zhí)行程序
    $childList[$pid] = 1;
}

// 延遲5秒誉碴,父進(jìn)程退出
sleep(5);
echo "({$parentPid})main progress end!\n";

執(zhí)行過(guò)程輸出:

孤兒進(jìn)程演示.png

可以看到宦棺,當(dāng)父進(jìn)程退出后,子進(jìn)程被 init 進(jìn)程收養(yǎng)黔帕。子進(jìn)程執(zhí)行完畢代咸,init 進(jìn)程完成對(duì)它的狀態(tài)收集工作。

僵尸進(jìn)程

一個(gè)進(jìn)程使用 fork 創(chuàng)建子進(jìn)程成黄,如果子進(jìn)程退出呐芥,而父進(jìn)程并沒(méi)有調(diào)用 wait 或 waitpid 獲取子進(jìn)程的狀態(tài)信息,那么子進(jìn)程的某些信息如進(jìn)程描述符仍然保存在系統(tǒng)中奋岁。這種進(jìn)程稱之為僵死進(jìn)程思瘟。

下面是1個(gè)關(guān)于僵尸進(jìn)程的例子,創(chuàng)建子進(jìn)程闻伶,然后讓父進(jìn)程睡眠 90s滨攻,讓子進(jìn)程先終止(注意和孤兒進(jìn)程例子的區(qū)別);這里子進(jìn)程結(jié)束后父進(jìn)程沒(méi)有調(diào)用 wait/waitpid 函數(shù)獲取其狀態(tài),用ps查看進(jìn)程狀態(tài)可以看出子進(jìn)程為僵尸狀態(tài)光绕。

示例代碼:

// 獲取當(dāng)前進(jìn)程ID
$parentPid = posix_getpid();
echo "parent progress pid:{$parentPid}\n";

$childList = array();

// 創(chuàng)建子進(jìn)程
$pid = pcntl_fork();
if ( $pid == -1) {
    // 創(chuàng)建失敗
    exit("fork progress error!\n");
} else if ($pid == 0) {
    $repeatNum = 10;
    for ( $i = 1; $i <= $repeatNum; $i++) {
        // 子進(jìn)程執(zhí)行程序
        $ppid = posix_getppid();
        $pid = posix_getpid();

        echo date('Y-m-d H:i:s') , ' ';
        echo "PPID:{$ppid} , PID:{$pid} child progress is running! {$i} \n";
        $rand = rand(1,3);
        sleep($rand);
    }

    echo date('Y-m-d H:i:s') , ' ';
    exit("({$pid})child progress end!\n");
} else {
    // 父進(jìn)程執(zhí)行程序
    $childList[$pid] = 1;
}

// 延遲90秒更鲁,父進(jìn)程退出
sleep(90);

echo date('Y-m-d H:i:s') , ' ';
echo "({$parentPid})main progress end!\n";

執(zhí)行過(guò)程輸出:

僵尸進(jìn)程運(yùn)行過(guò)程.png

僵尸進(jìn)程狀態(tài):

僵尸進(jìn)程進(jìn)程狀態(tài).png

任何一個(gè)子進(jìn)程 (init 除外) 在 exit() 之后,并非馬上就消失掉奇钞,而是留下一個(gè)稱為僵尸進(jìn)程 (Zombie) 的數(shù)據(jù)結(jié)構(gòu)澡为,等待父進(jìn)程處理。這是每個(gè)子進(jìn)程在結(jié)束時(shí)都要經(jīng)過(guò)的階段景埃。如果子進(jìn)程在 exit() 之后媒至,父進(jìn)程沒(méi)有來(lái)得及處理,這時(shí)用 ps 命令就能看到子進(jìn)程的狀態(tài)是“Z”谷徙。如果父進(jìn)程能及時(shí) 處理拒啰,可能用 ps 命令就來(lái)不及看到子進(jìn)程的僵尸狀態(tài),但這并不等于子進(jìn)程不經(jīng)過(guò)僵尸狀態(tài)完慧。 如果父進(jìn)程在子進(jìn)程結(jié)束之前退出谋旦,則子進(jìn)程將由 init 接管。init 將會(huì)以父進(jìn)程的身份對(duì)僵尸狀態(tài)的子進(jìn)程進(jìn)行處理屈尼。

僵尸進(jìn)程的危害:

僵尸進(jìn)程會(huì)在系統(tǒng)中保留其某些信息如進(jìn)程描述符册着、進(jìn)程 id 等等。以進(jìn)程 id 為例脾歧,系統(tǒng)中可用的進(jìn)程 id 是有限的甲捏,如果由于系統(tǒng)中大量的僵尸進(jìn)程占用進(jìn)程 id,就會(huì)導(dǎo)致因?yàn)闆](méi)有可用的進(jìn)程 id 系統(tǒng)不能產(chǎn)生新的進(jìn)程鞭执,這種問(wèn)題可就大了司顿,這就是僵尸進(jìn)程帶來(lái)的危害。因此大部分情況下兄纺,我們都應(yīng)當(dāng)避免僵尸進(jìn)程的產(chǎn)生大溜。

如何消除僵尸進(jìn)程:

嚴(yán)格地來(lái)說(shuō),僵死進(jìn)程并不是問(wèn)題的根源估脆,罪魁禍?zhǔn)资钱a(chǎn)生出大量僵死進(jìn)程的那個(gè)父進(jìn)程钦奋。因此,當(dāng)我們尋求如何消滅系統(tǒng)中大量的僵死進(jìn)程時(shí)旁蔼,答案就是把產(chǎn)生大量僵死進(jìn)程的那個(gè)元兇槍斃掉(也就是通過(guò) kill 發(fā)送 SIGTERM 或者 SIGKILL 信號(hào))锨苏。

槍斃了元兇進(jìn)程之后,它產(chǎn)生的僵死進(jìn)程就變成了孤兒進(jìn)程棺聊,這些孤兒進(jìn)程會(huì)被 init 進(jìn)程接管伞租,init 進(jìn)程會(huì) wait() 這些孤兒進(jìn)程,釋放它們占用的系統(tǒng)進(jìn)程表中的資源限佩。這樣葵诈,這些已經(jīng)僵死的孤兒進(jìn)程就能瞑目而去了裸弦。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市作喘,隨后出現(xiàn)的幾起案子理疙,更是在濱河造成了極大的恐慌,老刑警劉巖泞坦,帶你破解...
    沈念sama閱讀 222,590評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件窖贤,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡贰锁,警方通過(guò)查閱死者的電腦和手機(jī)赃梧,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,157評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)豌熄,“玉大人授嘀,你說(shuō)我怎么就攤上這事÷嘞眨” “怎么了蹄皱?”我有些...
    開封第一講書人閱讀 169,301評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)芯肤。 經(jīng)常有香客問(wèn)我巷折,道長(zhǎng),這世上最難降的妖魔是什么纷妆? 我笑而不...
    開封第一講書人閱讀 60,078評(píng)論 1 300
  • 正文 為了忘掉前任盔几,我火速辦了婚禮晴弃,結(jié)果婚禮上掩幢,老公的妹妹穿的比我還像新娘。我一直安慰自己上鞠,他們只是感情好际邻,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,082評(píng)論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著芍阎,像睡著了一般世曾。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上谴咸,一...
    開封第一講書人閱讀 52,682評(píng)論 1 312
  • 那天轮听,我揣著相機(jī)與錄音,去河邊找鬼岭佳。 笑死血巍,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的珊随。 我是一名探鬼主播述寡,決...
    沈念sama閱讀 41,155評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼柿隙,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了鲫凶?” 一聲冷哼從身側(cè)響起禀崖,我...
    開封第一講書人閱讀 40,098評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎螟炫,沒(méi)想到半個(gè)月后波附,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,638評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡昼钻,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,701評(píng)論 3 342
  • 正文 我和宋清朗相戀三年叶雹,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片换吧。...
    茶點(diǎn)故事閱讀 40,852評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡折晦,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出沾瓦,到底是詐尸還是另有隱情满着,我是刑警寧澤,帶...
    沈念sama閱讀 36,520評(píng)論 5 351
  • 正文 年R本政府宣布贯莺,位于F島的核電站风喇,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏缕探。R本人自食惡果不足惜魂莫,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,181評(píng)論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望爹耗。 院中可真熱鬧耙考,春花似錦、人聲如沸潭兽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,674評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)山卦。三九已至鞋邑,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間账蓉,已是汗流浹背枚碗。 一陣腳步聲響...
    開封第一講書人閱讀 33,788評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留铸本,地道東北人肮雨。 一個(gè)月前我還...
    沈念sama閱讀 49,279評(píng)論 3 379
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像归敬,于是被迫代替她去往敵國(guó)和親酷含。 傳聞我的和親對(duì)象是個(gè)殘疾皇子鄙早,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,851評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容