簡體   English   中英

等待子進程而不使用 wait()

[英]Wait for child process without using wait()

使用fork()時,是否可以確保子進程在父進程之前執行而不在父進程中使用wait()


這與操作系統Process API 章節中的作業問題有關:三個簡單的部分,一本免費的在線操作系統書籍。

問題說:

  1. 使用fork()編寫另一個程序。 子進程應該打印“hello”; 父進程應該打印“再見”。 你應該盡量確保子進程總是先打印; 您可以在調用父級中的wait()的情況下執行此操作嗎?

這是我使用wait()的解決方案:

#include <stdio.h>
#include <stdlib.h> // exit
#include <sys/wait.h> // wait
#include <unistd.h> // fork

int main(void) {
    int f = fork();
    if (f < 0) { // fork failed
        fprintf(stderr, "fork failed\n");
        exit(1);
    } else if (f == 0) { // child
        printf("hello\n");
    } else { // parent
        wait(NULL);
        printf("goodbye\n");
    }
}

經過思考,我決定最后一個問題的答案是“不,你不能”,但后來的一個問題似乎暗示你可以:

  1. 現在編寫一個程序,使用wait()等待子進程在父進程中完成。 wait()返回什么? 如果您在孩子中使用wait()會發生什么?

我對第二個問題的解釋是錯誤的嗎? 如果沒有,你如何做第一個問題所問的? 如何在不使用父級中的wait()的情況下讓子級先打印?

我希望這個答案還不算晚。

幾分鍾前,我給 Remiz(本書的作者)發了郵件,得到了這樣的回放(摘錄一些片段):

不調用 wait() 很難,而且不是重點。 你所做的——自己學習信號——是一個好兆頭,表明你將尋求更深層次的知識。 對你有益!

稍后,您將能夠使用共享內存段以及條件變量或信號量來解決此問題。

我不明白為什么第二個問題會暗示第一個問題的答案是“是”。

是的,有很多解決方案可以獲得所要求的內容,但當然我懷疑並不是所有問題/問題的“精神”都集中在fork/wait原語上。 關鍵是要記住,在分叉之后,你不能假設任何關於進程相對於彼此運行的方式。

為了確保子進程首先打印,您需要在兩個進程之間進行一種同步,並且有許多系統原語具有進程之間的“通信”語義(例如鎖、信號量、信號等)。 我懷疑其中之一是否會被她使用,因為它們通常會在此類課程的稍后部分介紹。

僅依賴於時間假設的任何其他嘗試(例如使用sleep或循環來“減慢”父級等)都可能導致失敗,這意味着您將無法證明它總是會成功。 即使測試可能會告訴您它似乎是正確的,您嘗試的大多數運行也不會具有導致失敗的不良特征。 請記住,除了在實時操作系統中,調度幾乎是公平並發的近似值。

筆記:

正如 Jonathan Leffler 評論的那樣,我還認為禁止使用其他類似wait的原語(又名wait4waitpid等)——“精神”論點。

在父級中創建一個管道。 fork之后,關閉 parent 中的 write 一半和 child 中的 read 一半。

然后, poll可讀性。 由於孩子從不給它寫信,它會等到孩子(以及所有孫子,除非你特別小心)不再存在,此時poll將給出“read with hangup”響應。 (或者,您實際上可以通過管道進行通信)。

您應該閱讀有關O_CLOEXEC的信息。 作為一般規則,除非您有充分的理由清除它,否則應始終設置該標志。

我所做的只是在 else 條件中放了一個 for 循環,這樣父進程不會立即完成,而子進程會先打印。 但我想這不是在技術上等待子進程和一個糟糕的解決方法來完成任務。 for(i=1000;i>0;i++); 而且,我認為使用這種(非道德)方法也不能保證孩子總是先打印。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM