2014-02-25 64 views
1

請在C考慮下面的代碼:確實linux永遠不會結束子進程,直到父節點結束?

int main() 
    { 
    pid_t cpid; 
    cpid = fork(); 
    if (cpid == -1) 
    { 
      perror("fork"); 
      return 0; 
    } 
    if (cpid == 0) 
    { 
      printf("I'm child\n"); 
      _exit(0); 
    } 
    else 
    { 
      while(1) 
      { 
        printf("I'm parent\n"); 
        sleep(1); 
      } 
    } 
    return 0; 
    } 

運行代碼後,我希望它運行的孩子,離開它一旦完成。 但是當我運行

pgrep executable_name 

ps fax 

它顯示的子進程ID,如果它只是工作過程的歷史垃圾或它確實沒有結束/終止我不知道孩子的過程?

在此先感謝

回答

5

孩子將一直等到父母死亡或父母用wait系統調用清除它。 (在孩子終止和清理之間的時間內,它被稱爲殭屍進程。)

原因是父級可能對子級的返回值或最終輸出感興趣,所以進程入口保持激活狀態直到查詢信息。

編輯:

使用SIGCHLD處理程序,立即清理,當他們死的過程不會阻塞示例代碼:

http://arsdnet.net/child.c

要留意的是,系統調用(如睡眠,選擇,或文件讀/寫)可以被信號中斷。這是你在unix中應該處理的正常事情 - 它們失敗並將errno設置爲EINTR。發生這種情況時,您可以再次嘗試完成操作。這就是爲什麼我的示例代碼在父代中調用了兩次睡眠 - 第一次長睡會被孩子死亡打斷,然後第二次較短的睡眠讓我們確認在父母死亡之前實際清理了進程。

順便說一句,信號處理程序通常不應該做太多,他們應該儘快返回,並避免不是線程安全的東西;通常不鼓勵在其中印刷。我在這裏做過,所以你可以看到發生的一切。

+2

爲了清楚起見:* only *當進程處於「殭屍」狀態時進程表條目存活;所有其他資源都被釋放。 – zwol

+0

好吧,這是一個解決方案,並感謝您給出的原因,但不等待父母,直到孩子的狀態改變?我想要叉的並行化在第一個地方 – madz

+1

是的,等待塊。你也可以設置一個SIGCHLD處理程序,並且只有等到它被觸發時才能確保它不會被阻塞。信號在小孩終止時發送。您也可以忽略它,孩子在父母結束時會自動清理。 –

2

你需要調用wait()父,否則子進程將永遠不會被收割(變成殭屍)。 *


*除非家長本身也退出。

+0

'_exit'和'_Exit'怎麼樣?它不應該是後者嗎? – Brian

+1

@GIJoe在符合C11和POSIX的任何系統上,'_exit'和'_Exit'完全相同。 C11委員會擔心(愚蠢地,IMNSHO)採用POSIX名稱來實現具有不同(但實際上相同)文本規範的功能。這些差異僅僅是因爲C11以不同於POSIX的方式描述事物,並不是因爲意圖不同。 – zwol

+0

如果您對子進程的狀態不感興趣,請忽略SIGCHLD信號,子進程將自動獲得。 – nos