???? 在讀《unix環境高級編程》時,發現忽然對僵死進程的處理機制很感興趣,經過查閱資料弄清楚了其中的原理,在這里做一個記錄。
???? 在一個進程調用? exit? 函數,或者? return? 語句,或者是調用? abort? 等函數終止后,總之不管進程是怎樣終止的,它們在終止之后,都會去執行內核中的一個代碼片斷。這個代碼片斷負責關閉終止進程打開的文件描述符,釋放終止進程占用的內存空間。但是,是否終止進程在系統中就從此消失,以后該進程在系統中,就再也找不到這個終止進程的一點蹤影呢,答案是否定的。
???? 一個進程在終止之后,會釋放它所占用的一切資源。但是會在進程表中保留該進程的一些生前的信息,比如進程ID,進程使用的CPU時間,退出狀態等。這時這個終止進程的狀態就稱之為僵死狀態,它要等待它的父進程來為它收尸。這時候在? linux? 系統中,僵死進程的狀態被打印為? ‘Z’,它的父進程通過調用? wait? 或者是? waitpid? 函數來為其善后。
停止docker、???? 僵死進程是怎么產生的呢?這是因為,在一個程序中,不斷的調用fork函數,卻沒有調用? wait? 或者? waitpid? 函數來做清除工作,而該程序又沒有終止,這樣就會在系統中產生僵死進程。解釋了這么多概念,不如給一個例子可能會更加的清晰,下面的一個例子用來在系統中產生僵死進程:
#include <stdio.h>
#include <unistd.h>int main(void)
{pid_t pid;while(1){if( (pid=fork())<0 ){printf("fork error\n");return -1;}else if( pid==0 ){printf("child\n");_exit(0);}else{sleep(1);}}return 0;
}
將程序編譯完成之后,執行,會每隔1秒鐘產生一個子進程。在子進程中輸出提示信息? child? 之后就立即退出。這個程序在執行的時候,我們再開一個終端,輸入命令:
ps aux | grep 'Z'
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
asus 3213 0.0 0.0 0 0 pts/0 Z+ 20:54 0:00 [a.out] <defunct>
asus 3214 0.0 0.0 0 0 pts/0 Z+ 20:54 0:00 [a.out] <defunct>
asus 3215 0.0 0.0 0 0 pts/0 Z+ 20:54 0:00 [a.out] <defunct>
asus 3217 0.0 0.0 0 0 pts/0 Z+ 20:54 0:00 [a.out] <defunct>
asus 3271 0.0 0.0 0 0 pts/0 Z+ 20:54 0:00 [a.out] <defunct>
asus 3272 0.0 0.0 0 0 pts/0 Z+ 20:54 0:00 [a.out] <defunct>
asus 3273 0.0 0.0 0 0 pts/0 Z+ 20:54 0:00 [a.out] <defunct>
asus 3274 0.0 0.0 0 0 pts/0 Z+ 20:54 0:00 [a.out] <defunct>
asus 3275 0.0 0.0 0 0 pts/0 Z+ 20:54 0:00 [a.out] <defunct>
asus 3276 0.0 0.0 0 0 pts/0 Z+ 20:54 0:00 [a.out] <defunct>
asus 3277 0.0 0.0 0 0 pts/0 Z+ 20:54 0:00 [a.out] <defunct>
asus 3282 0.0 0.0 0 0 pts/0 Z+ 20:54 0:00 [a.out] <defunct>
asus 3343 0.0 0.0 0 0 pts/0 Z+ 20:54 0:00 [a.out] <defunct>
asus 3344 0.0 0.0 0 0 pts/0 Z+ 20:54 0:00 [a.out] <defunct>
Linux,???? 感覺很奇怪吧,既然這些僵死進程都消失了,那么就一定有一個進程為系統種的僵死進程收尸,這個進程就是? init? 進程,它的PID為1。原來在? linux? 中,當一個進程的父進程終止時,這個進程就成為了孤兒進程,那么? init? 進程就是一個好心的人了,它專門收養孤兒進程。而? init? 進程又被實現為,當它有一個子進程終止時,就立即調用? wait? 函數來善后。所以就我們剛才的例子來說,當我們把程序終止后,所有僵死進程的父進程就變成了? init,而? init? 發現,哦,原來你們都是僵死進程啊,所以它給每一個僵死進程調用? wait? 函數,是使它們能夠安心離去。init? 進程的這種實現方式使得? linux? 系統中的僵死進程不會太多。當然,如果這個程序永遠不終止,那么系統中的僵死進程就會越來越多。
??? 注意:一個僵死進程在內存中已經沒有程序的正文和數據,所以不能使用? kill? 來殺死一個僵死的進程。只能通過殺死僵死進程的父進程來清除僵死進程,或者在父進程中調用wait或waipid函數來清除。
版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。
工作时间:8:00-18:00
客服电话
电子邮件
admin@qq.com
扫码二维码
获取最新动态