歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux基礎 >> Linux教程

Linux 的僵屍(zombie)進程

可能很少有人意識到,在一個進程調用了exit之後,該進程 並非馬上就消失掉,而是留下一個稱為僵屍進程(Zombie)的數據結構。在Linux進程的5種狀態中,僵屍進程是非常特殊的一種,它已經放棄了幾乎所 有內存空間,沒有任何可執行代碼,也不能被調度,僅僅在進程列表中保留一個位置,記載該進程的退出狀態等信息供其他進程收集,除此之外,僵屍進程不再占有 任何內存空間。

僵屍進程的來由,要追溯到Unix,Unix的設計者們設計這個東西並非是因為閒來無事想裝裝酷什麼的。上面說到,僵屍進程中保存著很多對程序員和系統管理員非常重要的信息,首先,這個進程是怎麼死亡的?是正常退出呢,還是出現了錯誤,還是被其它進程強迫退出的?也就是說,這個程序的退出碼是什麼?其次,這個進程占用的總系統CPU時間和總用戶CPU時間分別是多少?發生頁錯誤的數目和收到信號的數目。這些信息都被存儲在僵屍進程中,試想如果沒有僵屍進程,進程執行多長我們並不知道,一旦其退出,所有與之相關的信息都立刻都從系統中清除,而如果此時父進程或系統管理員需要用到,就只好干瞪眼了。

所以,進程退出後,系統會把該進程的狀態變成Zombie,然後給上一定的時間等著父進程來收集其退出信息,因為可能父進程正忙於別的事情來不及收集,所以,使用Zombie狀態表示進程退出了,正在等待父進程收集信息中。

Zombie進程不可以用kill命令清楚,因為進程已退出,如果需要清除這樣的進程,那麼需要清除其父進程,或是等很長的時間後被內核清除。因為Zombie的進程還占著個進程ID號呢,這樣的進程如果很多的話,不利於系統的進程調度。

下面,讓我們來看看一個示例:

/* zombie.c */
#include <sys/types.h>
#include <unistd.h>  main()
{
    pid_t pid;
    pid=fork();
    if(pid<0) { /* 如果出錯 */
        printf("error occurred!\n");
    }else if(pid==0){ /* 如果是子進程 */
        exit(0);
    }else{  /* 如果是父進程 */
        sleep(60);  /* 休眠60秒 */
        wait(NULL); /* 收集僵屍進程 */
    }
}

編譯這個程序:
 
$ cc zombie.c -o zombie
 
後台運行程序,以使我們能夠執行下一條命令
 
$ ./zombie &
[1] 1217
 
列一下系統內的進程
 
$ ps -ax
... ...
1137 pts/0 S 0:00 -bash
1217 pts/0 S 0:00 ./zombie
1218 pts/0 Z 0:00 [zombie]
1578 pts/0 R 0:00 ps -ax
 
其中的”Z”就是僵屍進程的標志,它表示1218號進程現在就是一個僵屍進程。
 
收集Zombie進程的信息,並終結這些僵屍進程,需要我們在父進程中使用waitpid調用和wait調用。這兩者的作用都是收集僵屍進程留下的信息,同時使這個進程徹底消失。

Copyright © Linux教程網 All Rights Reserved