1. 程式人生 > >fork函式_例項(3)呼叫兩次以避免僵死程序

fork函式_例項(3)呼叫兩次以避免僵死程序

--------參考文獻   W.Richard Stevens, Stephen A.Rago.UNIX環境高階程式設計[M].北京:人民郵電出版社,2014.6:189-190.

一、 相關概念 

1.1 僵死程序

一個已經終止,但是其父程序尚未對其進行善後處理(獲取終止子程序的有關資訊、釋放它仍佔用的資源)的程序被稱為僵死程序(zombie)。ps(1)命令將僵死程序的狀態列印為Z。如果編寫一個長期執行的程式,它fork了很多子程序,那麼除非父程序等待取得子程序的終止狀態,不然這些子程序終止後就會變成僵死程序。

帶來的問題就是——父程序不對終止的子程序進行處理(子程序太多,處理不過來),子程序會佔用資源直到父程序終止!這是一個極大的浪費。

1.2 init程序

init被編寫成無論何時只要有一個子程序終止,init就會呼叫wait函式取得其終止狀態。這樣也就防止了在系統中塞滿僵死程序。

二、 處理辦法

2.1 思路

fork兩次以避免僵死程序。如果一個程序fork一個子程序,但不要它等待子程序終止(不去管子程序),也不希望子程序處於僵死狀態直到父程序終止(僵死後光佔用資源沒有處理事務)。能否實現子程序不需要父程序管理但是會自動去進行善後?父程序結束,僵死子程序們會被init程序收養——這是自然的!有沒有什麼辦法?父程序沒有結束,父程序建立的子程序們手動交付給init程序,這樣的話,創建出來的子程序就不需要父程序去負責管理了。

圖1 示意圖

 如圖1 所示,通過這一層間接性,就實現避免僵死程序。

2.2 程式碼實現

#include<stdlib.h>      //exit()
#include<sys/wait.h>    //waitpid()
#include<stdio.h>       //printf()

int                                                                             
main()
{
    pid_t pid;
    pid = fork();
    if(pid < 0)
        printf("fork error!\n");
    else if(0 == pid){  //first chld
        pid = fork();
        if(pid < 0)
            printf("fork error!\n");
        else if(pid > 0)
            exit(0);    /*parent from second fork == first chld*/
        /*
         * We're the second chld; our parent becomes init as soon
         * as out real parent calls exit() in the statement above,
         * Here's  where we'd continue executing, knowing that when 
         * we're done, init will reap out status.
         */
        
        sleep(2);
        printf("second chld, parent pid = %ld\n", (long)getppid());
        exit(0);
    }

    if(waitpid(pid, NULL, 0) != pid)    /*wait for the first chld*/
        printf("waitpid error!\n");

    /*
     * We're the parent(the orginal process); we continue executing,
     * knowing that we're not the parent of the second chld. 
     */
    exit(0);
}                                                                             
圖2 Linux下執行結果