linux僵死進程

來源:互聯網
上載者:User

http://blog.chinaunix.net/uid-23089249-id-210808.html

 

一個進程在調用exit命令結束自己的生命的時候,其實它並沒有真正的被銷毀, 而是留下一個稱為僵死進程(Zombie)的資料結構(系統調用exit,它的作用是使進程退出,但也僅僅限於將一個正常的進程變成一個僵死進程,並不能將其完全銷毀)。

 

一、僵死進程的產生
    在每個進程退出的時候,核心釋放該進程所有的資源,包括開啟的檔案,佔用的記憶體等,但是仍然為其保留一定的資訊(包括進程號the process ID,退出狀態the 
termination status of the process,已耗用時間the amount of CPU time taken by the process等), 直到父進程通過wait/waitpid來取時才釋放。此時該進程處於僵死狀態,該進程成為僵死進程(Zombie Process)。 這保證了父進程可以擷取到子進程結束時的狀態資訊。
    在Linux進程的狀態中,僵死進程是非常特殊的一種,它已經放棄了幾乎所有記憶體空間,沒有任何可執行代碼,也不能被調度,僅僅在進程列表中保留一個位置,記載該進程的退出狀態等資訊供其他進程收集,除此之外,僵死進程不再佔有任何記憶體空間。它需要它的父進程來為它收屍,如果他的父進程沒安裝SIGCHLD訊號處理函數調用wait或waitpid()等待子進程結束,又沒有顯式忽略該訊號,那麼它就一直保持僵死狀態,如果這時父進程結束了,僵死的子進程成為"孤兒進程",過繼給1號進程init,init始終會負責清理僵死進程,它產生的所有僵死進程也跟著消失(每個進程結束的時候,系統都會掃描當前系統中所啟動並執行所有進程, 看有沒有哪個進程是剛剛結束的這個進程的子進程,如果是的話,就由Init來接管他,成為他的父進程)。但是如果如果父進程是一個迴圈,不會結束,那麼子進程就會一直保持僵死狀態,這就是為什麼系統中有時會有很多的僵死進程。怎麼查看僵死進程,利用命令ps,可以看到有標記為Z的進程就是僵死進程。

 

尋找所有的僵死進程

 ps -A -o stat,ppid,pid,cmd | grep -e '^[Zz]' 

 

二、僵死進程的危害
    如果父進程不調用wait/waitpid的話, 那麼保留的那段資訊就不會釋放,其進程號會一定被佔用,但是系統所能使用的進程號是有限的,如果產生了大量的僵死進程,將因為沒有可用的進程號而導致系統不能產生新的進程。 

 

三、僵死進程的避免 
1、父進程通過wait和waitpid等函數等待子進程結束,這會導致父進程掛起 
2、如果父進程很忙,那麼可以用signal函數為SIGCHLD安裝訊號處理函數。子進程結束後,父進程會收到該訊號,可以在訊號處理函數中調用wait回收 。
3、如果父進程不關心子進程什麼時候結束,那麼可以用signal(SIGCHLD, SIG_IGN)通知核心,自己對子進程的結束不感興趣,那麼子進程結束後,核心會回收, 並不再給父進程
發送訊號。
或用sigaction函數為SIGCHLD設定SA_NOCLDWAIT,這樣子進程結束後,就不會進入僵死狀態
 struct sigaction sa; 
 sa.sa_handler = SIG_IGN; 
 sa.sa_flags = SA_NOCLDWAIT; 
 sigemptyset(&sa.sa_mask); 
 sigaction(SIGCHLD, &sa, NULL); 
4、fork兩次,父進程fork一個子進程,然後繼續工作,子進程fork一個孫進程後退出,那麼孫進程被init接管,孫進程結束後,init會回收。不過子進程的回收還要父進程來做。

  1.     int nStatus;
  2.     pid_t pid;
  3.     
  4.     pid = vfork();            //產生子進程
  5.     if (pid > 0)            //父進程
  6.     {
  7.         waitpid(pid, &nStatus, 0);    //等待子進程結束,否則子進程會成為僵死進程,一直存在,即便子進程已結束執行
  8.     }
  9.     else if (0 == pid)        //子進程
  10.     {
  11.         pid = vfork();        //產生孫進程
  12.         if (pid > 0) 
  13.         {
  14.             exit(0);        //子進程退出,孫進程過繼給init進程,其退出狀態也由init進程處理,與原有父進程無關
  15.         }
  16.         else if (0 == pid)    //孫進程
  17.         {
  18.             if (execlp("ls", "ls", NULL) < 0)
  19.             {
  20.                 perror("execlp");
  21.                 exit(-1);
  22.             }
  23.         }
  24.         else
  25.         { 
  26.             perror("vfork(child)"); 
  27.         } 
  28.     }
  29.     else
  30.     { 
  31.         perror("vfork(parent)"); 
  32.     } 
  33. }

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.