簡體   English   中英

子進程退出時,父級應如何關閉管道文件描述符

[英]How should parent close pipe file descriptor when child process exits

我正在創建一個TCP服務,每次客戶端連接時都會派生一個新進程。 在派生之前,我先建立了一個管道,以便孩子可以將在連接期間收集的統計信息發送回父母。 父級關閉寫入端,子級關閉讀取端,並且父級維護一組讀取端文件描述符,每個子描述符一個。

當孩子完成連接並退出時,我不確定如何處理這些文件描述符。 孩子是否需要通過管道通知父母即將退出,以便父母可以關閉管道? 還是父母可以在孩子退出並關閉后自動檢測到破裂的管道?

父程序中的代碼正在運行一個帶有select()的循環,以檢測偵聽套接字和子級管道的讀取端上的活動。 每個孩子在奔跑時都可以向父母發送多個消息。

通常,當子進程退出時,父進程應如何處理管道文件描述符?

第一次通過:之前很明顯,存在一個使用select()的循環,並且子代發送了多條消息。

如果父進程維護文件描述符數組,則還需要將每個文件描述符與子進程關聯。 如果孩子在死前發送了一條小的統計消息,那么當主程序等待死亡的孩子時,它將知道哪個孩子死了,因此可以關閉剛剛發現孩子死亡的孩子的文件描述符(確保通過進行一次或多次最終讀取,管道為空)。

另一種機制是使用select()poll()或一個相關函數,該函數報告對文件描述符的讀取操作何時掛起。 當它從管道檢測到EOF(讀取的零字節)時,它知道該子項已死亡。 但是,這可能比較麻煩。

從您的問題尚不清楚,子進程退出時是否有單個消息,或者在子進程正在工作時是否有“意識流”統計報告。 如果只有一條消息(小於管道緩沖區的大小),那么生活就很簡單。 如果有消息流或消息的長度大於管道緩沖區的大小,則您必須更仔細地考慮協調問題-您不能僅在孩子死后才能檢測到消息。

第二遍:在獲得額外信息之后。

如果您已經使用select()一個循環中,那么當一個孩子死了,你會得到一個“管准備好讀”的指示select()您將得到從0字節read()這表明在該管EOF 。 然后,您應該關閉該管道(並可能使用W_NOHANG等待一個或多個帶有waitpid()孩子-應該至少要收集一具屍體-這樣您才能避免僵屍在漫長的時間內四處W_NOHANG

對您的最后一個問題的嚴格回答是:當唯一一個擁有寫末端的子項死亡時,父節點應關閉該管道的讀末端以釋放資源以供以后重用。

在您的情況下,父進程應在分叉后立即關閉管道的寫入端。 然后,它可以讀取其統計數據,直到EOF(文件結束),然后關閉管道的讀取端。

當您寫入管道但沒有打開可從該管道讀取的fd時,就會發生broken pipe 因此,這不適用於您的情況。 在您的情況下,由於您的父級正在從管道中讀取數據,因此在子級退出時它應該讀取EOF (如果您已正確關閉了父級進程中的寫端,否則它將阻塞,因為它假定仍然有需要讀取的內容)未來)。 然后,您可以在父進程中安全關閉read fd。

一般來說

如果父級寫入而子級讀取,則您確實需要擔心子級關閉讀取fd時broken pipe ,而父級會在繼續寫入管道時得到SIGPIPE。 默認情況下,SIGPIPE會終止該過程,因此您可能想要設置一個信號處理程序以使其執行所需的任何操作(如果您不希望它僅終止)。

暫無
暫無

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

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