所謂zombie process(殭屍行程)的成因,在於某行程已結束,但其父行程(parent
process)並未取得該行程之結束狀態,則該行程就會變成zombie
process,直到其父行程呼叫wait()取得該行程結束狀態。用更精確的說法,來自Advanced Programming in the
Unix Environment這本書:
Zombie process會造成kernel內部有多餘的一筆process資料儲存,佔了一筆資料量(process id, termination status, the amount of CPU time taken by the process等等資訊),但其卻已經結束了,若是系統load很高,造成的影響就更大了,譬如process數量到達上限,又發生有zombie process,可能就會產生無法執行程式的問題。因此我們必須避免zombie process的產生。

下圖的情形,則會產生zombie process:在A還沒wait或exit之前,若B已結束,則這段時間內B就是zombie process了。

該如何避免zombie process呢?或許google一下也知道吧!由於Linux會在一個process的父行程結束時,自動把該行程的父行程變成init,也就是讓該process由init接管。因此,假設我們的父行程必須作自己的事情,並不想wait子行程結束而block時,我們可以利用兩次fork,讓第一次fork的process馬上結束,則第二次fork的grandchild將會自動變成init的子行程,這樣一來,最原先的行程將不必在作wait的動作,而該行程從此也跟第二次fork出來的行程毫無親屬關係了。兩者各作各的,誰先結束並不會影響對方。這就是fork兩次的用意:

如上圖所示,寫成程式大概會像是這樣(注意:裡面沒有錯誤處理的code):
waitpid(pid);
parent does things here...
//child
if fork()
//child
exit;
else
//granchild
grandchild does things here...

![]() | What is Process |
![]() | Why Process |
![]() | How Process Works |
![]() | Process的產生 |
fork-and-exec是UNIX中所有process運作的模式。系統bootup的時候,第一個被執行的process(程式),其pid為1;經由fork-and-exec程序,啟動各個必要的process,而形成一個功能完整的作業系統。
狰
fork是UNIX一個系統呼叫(system call),process fork時,會複製一個跟自己完全一模一樣的process (with different pid),並利用系統呼叫完成之傳回值,來區分parent process 與child process,而分別賦予child process不同的功能。
process於程式執行過程中,利用exec執行另一不同的程式,這個程式並且會完全取代原有程式(with the same pid)。
![]() | Process的結束 |
process及child process。
如果因某些原因,parent process在其結束前即已不存在,此 process即成為所謂的Zombie process(or defunct process),無法正常結束。
Child process通常會隨著parent process結束而結束,因此手動結束process “init”(系統第一個啟動的process, pid為1),將會造成系統當機。(目前大部分的UNIX作業系統會禁止你手動停止init的執行)
![]() | Monitor Proces with Command : ps
|
![]() | ps 各欄位意義 | ||||||||||||||||||||||||||||||||||||||||
![]() | Process的管理相關指令
| ||||||||||||||||||||||||||||||||||||||||
![]() | Monitor Proces with Command Utility : "top" (top is not a standard UNIX Command) |
[root@nmc ~]# top
3:56pm up 53 days, 22:03, 1 user, load average: 0.00, 0.00, 0.00
60 processes: 59 sleeping, 1 running, 0 zombie, 0 stopped
CPU states: 0.7% user, 1.9% system, 0.0% nice, 97.2% idle
Mem: 128144K av, 124852K used, 3292K free, 60620K shrd, 82020K buff
Swap: 104412K av, 452K used, 103960K free15784K cached
PID USER PRI NI SIZE RSS SHARE STAT LIB %CPU %MEM TIME COMMAND 19512 root 15 0 860 860 664 R 0 2.9 0.6 0:00 top 1 root 0 0 472 472 400 S 0 0.0 0.3 0:04 init 2 root 0 0 0 0 0 SW 0 0.0 0.0 0:00 kflushd 3 root 0 0 0 0 0 SW 0 0.0 0.0 0:10 kupdate 4 root 0 0 0 0 0 SW 0 0.0 0.0 0:00 kpiod 5 root 0 0 0 0 0 SW 0 0.0 0.0 0:01 kswapd 319 bin 0 0 412 400 320 S 0 0.0 0.3 0:00 portmap 333 root 0 0 0 0 0 SW 0 0.0 0.0 0:00 lockd 334 root 0 0 0 0 0 SW 0 0.0 0.0 0:00 rpciod 343 root 0 0 520 516 428 S 0 0.0 0.4 0:00 rpc.statd 396 root 0 0 472 468 376 S 0 0.0 0.3 0:05 syslogd 405 root 0 0 616 612 304 S 0 0.0 0.4 0:00 klogd 419 nobody 0 0 552 540 428 S 0 0.0 0.4 0:00 identd 422 nobody 0 0 552 540 428 S 0 0.0 0.4 0:00 identd 423 nobody 0 0 552 540 428 S 0 0.0 0.4 0:00 identd 425 nobody 0 0 552 540 428 S 0 0.0 0.4 0:00 identd 426 nobody 0 0 552 540 428 S 0 0.0 0.4 0:00 identd
![]() | top Commands
|