簡體   English   中英

C IPC等待孩子

[英]C IPC waiting for child

所以我有一個程序,它創建一個子進程並執行一個命令(例如,ls)。 然后,父母將使用管道發送給孩子並從孩子那里取得。 當我從命令行輸入命令時,這很好用。

但是,當輸入來自文件時,似乎孩子沒有足夠的時間來運行,並且從管道讀取時我得到NULL - 即使會有來自它的信息。

沒有使用sleep(),有沒有更好的方法來確保孩子在嘗試閱讀之前已經運行了?

非常感謝!

如果您沒有將管道文件描述符設置為非阻塞,那么應該沒有問題。 管道上的任何讀數都會阻塞,直到孩子產生輸出; 如果您需要響應多個文件描述符(例如,來自用戶的標准輸入和來自子進程的管道),請使用select()poll()

我假設fgets()返回NULL。 這表示文件結束(意味着孩子已關閉管道的末尾)或錯誤。 你可以使用feof()ferror()來檢查其中哪一個是真的。 在錯誤情況下使用perror()來查看錯誤實際是什么。

問題是你對孩子有多少控制? 如果您自己編寫孩子,那么您可以讓孩子在已啟動的共享內存中設置一個標志(或觸摸文件或您想要的任何癢癢),然后只有在您知道孩子在線運行它之后。

如果您無法控制子進程,那么仍然可以通過使用您自己的腳本包裝子進程來實現上述解決方案,該腳本首先啟動子進程然后設置共享內存。這可以是shell腳本的形式,如如下

#!/bin/sh

$CHILD
my_app_that_set_the_flag

最后另一個選擇是繼續等待從管道中獲取NULL,顯然這會導致無限循環,但如果你不能指望你總會在管道上得到一些東西

您的父線程需要等到子項准備好后再嘗試從管道讀取。 有幾種方法可以做到這一點。

首先,您可以使用條件變量。 聲明兩個線程都可以訪問的變量並將其設置為0 當父級已准備好閱讀時,您的子線程將其設置為1 父將等到變量變為1 (使用while(!condvar) sleep(1); ),然后它將從管道中讀取並將變量重置為0以便子項知道父項已完成。

另一種選擇是使用一種進程間通信形式,例如信號 與條件變量方法類似,子線程將執行其工作,然后在完成時向父線程發送信號。 父線程將一直等到它從管道讀取之前接收到信號,然后它可以向子節點發送一個信號,指示它已完成。

編輯:由於您使用fork而不是使用線程生成子進程,因此您不能在此處使用條件變量(父級和子級將具有單獨的副本)。

相反,您可以使用signal()kill()函數在進程之間發送信號。 在分叉之前,使用getpid存儲父pid的副本(用於子進程)。 還存儲fork的返回值,因為它將包含子的pid。

要向其他進程發送信號,請使用以下內容:

kill(parent_pid, SIGUSR1);

接收過程需要設置信號處理程序。 例如:

int signal_received = 0;
void signal_handler(int signal_num) {
    if (signal_num == SIGUSR1)
        signal_received = 1;
}

signal(SIGUSR1, signal_handler);

現在,只要進程收到信號編號SIGUSR1就會自動調用signal_handler函數。 你的線程會在一個循環中等待,看着這個變量改變使用類似的東西:

while (1) { // Signal processing loop
    // Wait here for a signal to come in
    while (!signal_received) { sleep(1); }

    // Wake up and do something
    read_from_pipe();
    ...
    signal_received = 0;
}

暫無
暫無

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

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