linux 管道關閉無用的寫入端

2021-10-12 16:27:13 字數 1444 閱讀 8630

管道的讀寫是是符合生產者--消費者模型。寫入內容對應於生產內容;讀取管道對應於消費內容。當所有的生產者都退場以後,消費者應當有方法判斷這種情況,俄日不是傻傻等待已經不存在的生產者繼續生產,以至於陷入永久的阻塞

如何判斷?

答案是通過檔案結束識別符號eof。當對管道的讀取端呼叫read函式返回0 時,就意味著所有的生產者都已經退場了,作為消費者的讀取程序,就不需要繼續等待新的內容了。什麼情況下對管道讀取端的描述符呼叫read會返回0呢?

所有的相關程序都已經關閉了管道的寫入端描述符

管道中的已有內容已經被全部讀取

同時滿足上面兩個條件,對管道讀取端描述符呼叫read返回值就是0,根據這個消費者就可以判斷管道的內容生產者已經不存在了,也不用等待了,可以關閉管道讀取端描述符了。

從上面的討論可以看出,如果負責讀取的程序,或者與通訊無關的程序,不關閉管道的寫入端描述符,那麼就會有管道寫入端描述符的洩漏。當所有負責寫入的程序都關閉了寫入端描述符後,負責讀取的程序呼叫read時,仍會阻塞於此(如果沒有設定o_nonblock標誌位的話),且永不返回。這是因為核心維護的引用計數。發現還有程序可寫入管道,因此read函式依舊會阻塞。

下面這個例子可驗證一下:

#include #include #include #include #include #include int main()

pid = fork();

if(pid == 0)

}close(pipe_fd[0]);

exit(0);

}else if(pid > 0)

else

/*父程序 sleep 15秒,在這15秒內子程序阻塞在read */

sleep(15);

printf("[parent] will close the last write end of pipe\n");

close(pipe_fd[1]); //父程序寫完1024位元組後,關閉了寫入端

sleep(2);

return 0;

}}

在上面的例子中,父子程序通過管道進行通訊,父程序關閉了管道的讀取端描述符,子程序關閉了管道的寫入端描述符。父程序寫入了1024位元組,子程序則在迴圈體內呼叫read,每次嘗試讀取1000位元組,子程序很快讀取了父程序產生的1024位元組,但是父程序並沒有立刻關閉管道的寫入端,而是睡眠了15秒之後,才關閉寫入端描述符。從子程序讀完父程序寫入的1024位元組開始,到父程序關閉管道寫入端的這15秒內,子程序實際是阻塞在read函式上面的。當父程序關閉管道的寫入端,子程序呼叫的read函式才得以返回,返回值是0。子程序看到返回值是0之後,意識到管道的寫入端也不復存在了,所以他沒有必要繼續去讀了,於是子程序就跳出了迴圈體。

該程式還可以驗證:linux管道讀寫,驗證讀寫位元組大小不一致,出現的等待阻塞。

關於pipe管道的讀寫端關閉問題

通過pipe在核心中建立乙個檔案,然後可以實現兩個程序通訊 管道是一種最基本的ipc機制,由 pipe 函式建立 1 include 2 int pipe int filedes 2 呼叫 pipe 函式時在核心中開闢一塊緩衝區 稱為管道 用於通訊,它有乙個讀端乙個寫端,然後通過 filedes 引...

cent os 關閉掉無用的kernel模組

最近優化magento花了很多時間,當然也花了很多時間有linux系統的管理配置方面,總知是訂單式的學習.用到什麼就學習什麼,之後再系統的總結.最近困擾了很久,雖然說很簡單.就是如何去掉無用的一些kernel模組,這樣也可以節省一些記憶體,雖然對magento來講這點記憶體不算什麼,當然對安全性也有...

好玩或許無用的Linux命令

1 sudo apt get install hollywood cmatrix,感覺像是黑客帝國裡面的畫面一樣牛掰。2 sudo apt get install oneko,執行oneko 如果你認為linux終端只是字元和游標,沒有什麼其它更豐富的表現形式了,那你就大錯特錯了,oneko 命令就...