溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

Linux中怎么殺死defunct進(jìn)程

發(fā)布時(shí)間:2021-08-11 17:10:00 來(lái)源:億速云 閱讀:238 作者:Leah 欄目:系統(tǒng)運(yùn)維

Linux中怎么殺死defunct進(jìn)程,相信很多沒(méi)有經(jīng)驗(yàn)的人對(duì)此束手無(wú)策,為此本文總結(jié)了問(wèn)題出現(xiàn)的原因和解決方法,通過(guò)這篇文章希望你能解決這個(gè)問(wèn)題。

一、什么是defunct進(jìn)程(僵尸進(jìn)程)
在 Linux 系統(tǒng)中,一個(gè)進(jìn)程結(jié)束了,但是他的父進(jìn)程沒(méi)有等待(調(diào)用wait / waitpid)他,那么他將變成一個(gè)僵尸進(jìn)程。當(dāng)用ps命令觀(guān)察進(jìn)程的執(zhí)行狀態(tài)時(shí),看到這些進(jìn)程的狀態(tài)欄為defunct。僵尸進(jìn)程是一個(gè)早已死亡的進(jìn)程,但在進(jìn)程表(processs table)中仍占了一個(gè)位置(slot)。
但是如果該進(jìn)程的父進(jìn)程已經(jīng)先結(jié)束了,那么該進(jìn)程就不會(huì)變成僵尸進(jìn)程。因?yàn)槊總€(gè)進(jìn)程結(jié)束的時(shí)候,系統(tǒng)都會(huì)掃描當(dāng)前系統(tǒng)中所運(yùn)行的所有進(jìn)程,看看有沒(méi)有哪個(gè)進(jìn)程是剛剛結(jié)束的這個(gè)進(jìn)程的子進(jìn)程,如果是的話(huà),就由Init進(jìn)程來(lái)接管他,成為他的父進(jìn)程,從而保證每個(gè)進(jìn)程都會(huì)有一個(gè)父進(jìn)程。而Init進(jìn)程會(huì)自動(dòng)wait其子進(jìn)程,因此被Init接管的所有進(jìn)程都不會(huì)變成僵尸進(jìn)程。

二、 Linux下進(jìn)程的運(yùn)作方式
每個(gè) Linux進(jìn)程在進(jìn)程表里都有一個(gè)進(jìn)入點(diǎn)(entry),核心進(jìn)程執(zhí)行該進(jìn)程時(shí)使用到的一切信息都存儲(chǔ)在進(jìn)入點(diǎn)。當(dāng)用 ps 命令察看系統(tǒng)中的進(jìn)程信息時(shí),看到的就是進(jìn)程表中的相關(guān)數(shù)據(jù)。當(dāng)以fork()系統(tǒng)調(diào)用建立一個(gè)新的進(jìn)程后,核心進(jìn)程就會(huì)在進(jìn)程表中給這個(gè)新進(jìn)程分配一個(gè)進(jìn)入點(diǎn),然后將相關(guān)信息存儲(chǔ)在該進(jìn)入點(diǎn)所對(duì)應(yīng)的進(jìn)程表內(nèi)。這些信息中有一項(xiàng)是其父進(jìn)程的識(shí)別碼。
子進(jìn)程的結(jié)束和父進(jìn)程的運(yùn)行是一個(gè)異步過(guò)程,即父進(jìn)程永遠(yuǎn)無(wú)法預(yù)測(cè)子進(jìn)程到底什么時(shí)候結(jié)束。那么會(huì)不會(huì)因?yàn)楦高M(jìn)程太忙來(lái)不及 wait 子進(jìn)程,或者說(shuō)不知道子進(jìn)程什么時(shí)候結(jié)束,而丟失子進(jìn)程結(jié)束時(shí)的狀態(tài)信息呢?
不會(huì)。因?yàn)?Linux提供了一種機(jī)制可以保證,只要父進(jìn)程想知道子進(jìn)程結(jié)束時(shí)的狀態(tài)信息,就可以得到。這種機(jī)制就是:當(dāng)子進(jìn)程走完了自己的生命周期后,它會(huì)執(zhí)行exit()系統(tǒng)調(diào)用,內(nèi)核釋放該進(jìn)程所有的資源,包括打開(kāi)的文件,占用的內(nèi)存等。但是仍然為其保留一定的信息(包括進(jìn)程號(hào)the process ID,退出碼exit code,退出狀態(tài)the terminationstatus of the process,運(yùn)行時(shí)間the amount of CPU time taken by the process等),這些數(shù)據(jù)會(huì)一直保留到系統(tǒng)將它傳遞給它的父進(jìn)程為止,直到父進(jìn)程通過(guò)wait / waitpid來(lái)取時(shí)才釋放。
也就是說(shuō),當(dāng)一個(gè)進(jìn)程死亡時(shí),它并不是完全的消失了。進(jìn)程終止,它不再運(yùn)行,但是還有一些殘留的數(shù)據(jù)等待父進(jìn)程收回。當(dāng)父進(jìn)程 fork() 一個(gè)子進(jìn)程后,它必須用 wait() (或者 waitpid())等待子進(jìn)程退出。正是這個(gè) wait() 動(dòng)作來(lái)讓子進(jìn)程的殘留數(shù)據(jù)消失。

三、僵尸進(jìn)程的危害
如果父進(jìn)程不調(diào)用wait / waitpid的話(huà),那么保留的那段信息就不會(huì)釋放,其進(jìn)程號(hào)就會(huì)一直被占用,但是系統(tǒng)的進(jìn)程表容量是有限的,所能使用的進(jìn)程號(hào)也是有限的,如果大量的產(chǎn)生僵尸進(jìn)程,將因?yàn)闆](méi)有可用的進(jìn)程號(hào)而導(dǎo)致系統(tǒng)不能產(chǎn)生新的進(jìn)程。
所以,defunct進(jìn)程不僅占用系統(tǒng)的內(nèi)存資源,影響系統(tǒng)的性能,而且如果其數(shù)目太多,還會(huì)導(dǎo)致系統(tǒng)癱瘓。而且,由于調(diào)度程序無(wú)法選中Defunct 進(jìn)程,所以不能用kill命令刪除Defunct 進(jìn)程,惟一的方法只有重啟系統(tǒng)。

四、如何殺死defunct進(jìn)程
defunct進(jìn)程是指出錯(cuò)損壞的進(jìn)程,父子進(jìn)程之間不會(huì)再通信。有時(shí),它們會(huì)演變成“僵尸進(jìn)程”,存留在你的系統(tǒng)中,直到系統(tǒng)重啟??梢試L試 “kill -9” 命令來(lái)清除,但多數(shù)時(shí)候不管用。
為了殺死這些defunct進(jìn)程,你有兩個(gè)選擇:
1.重啟你的計(jì)算機(jī)
2.繼續(xù)往下讀...
我們先看看系統(tǒng)中是否存在defunct進(jìn)程:

代碼如下:


$ ps -A | grep defunct


假設(shè)得到的輸出如下所示:

代碼如下:


8328 ? 00:00:00 mono <defunct>
8522 ? 00:00:01 mono <defunct>
13132 ? 00:00:00 mono <defunct>
25822 ? 00:00:00 ruby <defunct>
28383 ? 00:00:00 ruby <defunct>
18803 ? 00:00:00 ruby <defunct>


這意味著存在6個(gè)defunct進(jìn)程:3個(gè)mono進(jìn)程,以及3個(gè)ruby進(jìn)程。這些進(jìn)程之所以存在,可能是因?yàn)閼?yīng)用程序?qū)懙煤軤€或者用戶(hù)做了不常見(jiàn)的操作,在我這,一定是我寫(xiě)的mono C#程序存在嚴(yán)重問(wèn)題 :smile: 。
現(xiàn)在,我們來(lái)看看這些進(jìn)程的ID及其父進(jìn)程ID:

代碼如下:


$ ps -ef | grep defunct | more


以上命令的輸出如下:

代碼如下:


UID PID PPID ...
---------------------------------------------------------------
kenno 8328 6757 0 Mar22 ? 00:00:00 [mono] <defunct>
kenno 8522 6757 0 Mar22 ? 00:00:01 [mono] <defunct>
kenno 13132 6757 0 Mar23 ? 00:00:00 [mono] <defunct>
kenno 25822 25808 0 Mar27 ? 00:00:00 [ruby] <defunct>
kenno 28383 28366 0 Mar27 ? 00:00:00 [ruby] <defunct>
kenno 18803 18320 0 Apr02 ? 00:00:00 [ruby] <defunct>


UID:用戶(hù)ID
PID:進(jìn)程ID
PPID:父進(jìn)程ID
如果你使用命令 “kill -9 8328” 嘗試殺死ID為8328的進(jìn)程,可能會(huì)沒(méi)效果。要想成功殺死該進(jìn)程,需要對(duì)其父進(jìn)程(ID為6757)執(zhí)行kill命令($ kill -9 6757)。對(duì)所有這些進(jìn)程的父進(jìn)程ID應(yīng)用kill命令,并驗(yàn)證結(jié)果($ ps -A | grep defunct)。

看完上述內(nèi)容,你們掌握Linux中怎么殺死defunct進(jìn)程的方法了嗎?如果還想學(xué)到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注億速云行業(yè)資訊頻道,感謝各位的閱讀!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI