程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> 關於PHP編程 >> 父進程是init一定不會變僵屍進程嗎?

父進程是init一定不會變僵屍進程嗎?

編輯:關於PHP編程

父進程是init一定不會變僵屍進程嗎?


父進程是init一定不會變僵屍進程嗎?
——lvyilong316

工作中有次操作線上環境時發現有一個“Z”(僵屍)進程,當時首先想到的方法就是把這個進程的父進程干掉。但是ps下發現該進程的父進程已經是init了。這個情況讓我很迷惑,因為通常來說一旦init進程接管了Z狀態的進程就會調用wait將其回收。而且這是避免僵屍進程的一種重要手段,怎麼會出現這種情況呢?

後來仔細回想了下進程終止時的過程,忽然找到問題所在了。我們知道任何進程結束最終都會調用內核函數do_exit。而這個函數有兩個重要的事要完成:

(1)(作為父進程)給自己的子進程(如果存在)找一個新的父進程;

(2)(作為子進程)通知自己的父進程為自己“收屍”;

第一個事情比較簡單,如果要退出的進程時多線程進程,則可以將子進程托付給自己的兄弟線程,如果沒有這樣的線程,則托付給init進程;

第二件事情對於單線程的進程比較簡單,但多線程的進程就會復雜些。因為只有線程組的主線程才有資格通知父進程,線程組的其他線程終止時,並不通知父進程,也沒必要保留資源進入僵屍狀態,直接調用release_task函數釋放所有的資源就好。

由於父進程只認子進程的主線程,所以在線程組中,如果主線程終止了,但是線程組還有其他線程,那麼就不會通知父進程來收屍,直到線程組中最後一個線程退出時。換句話說:在用戶層面,可以調用pthread_exit讓主線程先“死”,但在內核態中,主線程的task_struct一定要保住,哪怕變為僵屍。

所以當主線程退出但是其他線程還在運行,這時主線程就會變為Z狀態,縱使init接管了主線程。

l測試代碼

  1. #include
  2. #include
  3. #include
  4. #include
  5. void thread_fun(void)
  6. {
  7. printf("begin thread...\n");
  8. sleep(100);
  9. printf("end thread...\n");
  10. }
  11. int main(int argc, char *argv[])
  12. {
  13. pthread_t tid;
  14. int ret;
  15. daemon(0, 0);//調用deamon是為了讓init接管主線程
  16. printf("process begin...\n");
  17. ret=pthread_create(&tid,NULL,(void *)thread_fun,NULL);
  18. if(ret !=0 )
  19. {
  20. printf("pthread error\n");
  21. exit(1);
  22. }
  23. printf("main thread is end...\n");
  24. pthread_exit(0);
  25. printf("never exce\n");
  26. }

我們創建線程執行sleep,然後主線程退出,當我們使用ps查看主線程狀態時結果如下:

18099 1 Zsl a.out 0.0 0.0

可以看到,雖然init接管了主線程,但是主線程依然是Z狀態。要想讓這個Z進程消失,有兩個辦法,一個是殺死整個進程,也就是kill 18099,在一個就是ps -eLf查找其他線程,然後kill掉。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved