前言
? ? ? ? 僵尸進程和孤兒進程是Linux中極為重要的兩個種進程狀態, 本文將會圍繞這三個問題: 是什么? 為什么? 如何產生的? 詳細的介紹這兩種進程; 以及一些使用場景.
?僵尸進程
?在了解孤兒進程之前, 需要先引入僵尸進程的概念;
?什么是僵尸進程?
僵尸進程: 就是處于僵死狀態的進程;
????????僵死狀態(Zombies)是一個比較特殊的狀態。當進程退出并且父進程, 沒有讀取到子進程退出的返回代碼時就會產生僵死(尸)進程
為什么會產生僵尸進程?
?????????進程 = 進程PCB + 進程的代碼和數據; 進程存在就一定會占用一定的空間;
????????為什么創建進程? 很簡單, 為了讓它幫我們完成某些任務;
????????進程執行完畢之后, 核心任務: 將進程PCB 以及進程的代碼和數據釋放掉;
????????父進程創建子進程, 讓子進程去完成某些任務, 那么父進程可能有需求: 需要知道子進程的任務完成情況;
????????子進程退出時, 會由OS將子進程的退出信息寫入到進程PCB中, 允許進程的代碼和數據被釋放, 但是進程PCB不會立即釋放, 要讓父進程知道 子進程退出的信息, 得知子進程退出的原因(正常退出或者異常退出);
? ? ? ? ?當一個進程退出了, 代碼和數據已經被釋放, 只要PCB中的退出信息還沒有被 OS或父進程讀取到, OS就必須維護這-退出進程的PCB, 此時的進程狀態就是Z狀態, 也就是僵尸狀態;
? ? ? ? ?只有被父進程讀取后(wait)后, PCB的狀態才會將Z狀態改為X狀態, 然后被OS回收;
危害 :
? ? ? ? 一個進程處于Z狀態, 父進程一直不讀取回收, 那么該進程的PCB就會一直存在, 造成內核級的內存泄露(內核資源浪費);
?????????這種危害主要在一些服務器中較為明顯, 服務器的服務會長時間的運行, 長時間的積累就會導致服務的效率變慢, 雖然重啟服務器可以將僵尸進程的PCB資源釋放, 但是對于服務器而言, 不可能輕易的關閉后重啟;
?模擬僵尸進程的產生:
int main()
{pid_t id = fork();if (id < 0) return 1;else if (id == 0) //子進程執行5秒后退出{int cnt = 5;while (cnt){printf("I am child , runing time:%d\n", cnt--);sleep(1);}printf("I am child ,dead!:%d\n", cnt--);exit(2);}else // 父進程一直運行, 但不回收子進程{while (1){printf("I am father, running times!\n");sleep(1);}}return 0;
}
?使用指令監控進程的狀態變化:
while :; do ps ajx | head -1 && ps ajx | grep myprocess | grep -v grep; sleep 1; done // myprocess為需要監控的進程名
?孤兒進程
?什么是孤兒進程?
? ? ? ? 父進程先退出,子進程就稱之為“孤兒進程”
父進程先退出,? 那么子進程退出時不就沒有進程來讀取子進程的PCB退出信息了嗎??
?為什么被1號進程領養?
? ? ? ? 為了避免子進程退出, 沒有進程讀取子進程PCB的情況發生;?
? ? ? ? 父進程一旦退出, 子進程如果還沒有執行完畢, 就會被OS領養, 當子進程執行完畢退出后, 由OS進行讀取回收;?
模擬孤兒進程的產生:
int main()
{pid_t id = fork();if (id < 0) return 1;else if (id == 0) // 子進程一直運行{while (1){printf("I am child ...\n");sleep(1);}}else // 父進程運行5秒后退出{int cnt = 5;while (cnt){printf("I am father, running time:%d\n", cnt--);sleep(1);}printf("I am father dead:%d\n", cnt--);exit(2);}return 0;
}
?監控指令:
while :; do ps ajx | head -1 && ps ajx | grep myprocess | grep -v grep; sleep 1; done // myprocess為需要監控的進程名
?孤兒進程在實際應用中的使用:
? ? ? ? 孤兒進程的特性在一些并發服務中可以使用,? 服務器服務接收請求, 對請求進行處理時可以讓任務處理的主進程創建子進程去執行, 而主進程立即退出, 此時子進程就會變成孤兒進程, 被OS領養, 當子進程執行完畢后, 由OS進行回收, 任務處理的進程也不需要一直的等待子進程處理完畢;
?
總結
? ? ? ? 孤兒進程是為了避免父進程退出, 造成子進程無法被讀取, 導致子進程變成僵尸進程的情況; 僵尸進程對于服務器服務來說危害極大, 在編寫服務時要特別注意; 好了以上便是本文的全部內容, 希望對你有所幫助,? 感謝閱讀!