您好,登錄后才能下訂單哦!
這篇文章給大家分享的是有關Linux管道的示例分析的內容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。
管道是最早出現的進程間通信的手段,在shell中執行命令,經常會將上一個命令的輸出作為下一個命令的輸入,由多個命令配合完成一件事情。管道的作用是在有親緣關系的進程之間傳遞消息,因為共同主先進程調用過pipe函數,打開的管道文件就會在fork之后,被各個后代進程所共享,打開的管道可以由其中一個進程寫入數據,然后另一個具有親屬關系的進程讀取。
嚴格來說,家族里面的多個進程都可以往同一個秘密場所里面扔消息,也可以都從同一個秘密場所里面取消息,但是真的這么做的話又會存在風險。管道實質是一個字節流,并非前面提到的消息,沒有消息的邊界。如果多個進程發送的字節流混在一起,則無法辨認出各自的內容。所以一般是兩個有親緣關系的進程用管道來通信。
一般來講,進程中數據流是單向的,并且是閱后即焚的。管道是一種文件,可以調用read、write和close等操作文件的接口來操作管道。另一方面管道又不是一種普通的文件,它屬于一種獨特的文件系統:pipefs。管道的本質是內核維護了一塊緩沖區與管道文件相關聯,對管道文件的操作,被內核轉換成對這塊緩沖區內存的操作。
Linux下創建管道函數:
int pipe(int pipefd[2])
成功調用pipe函數之后,會返回兩個打開的文件描述符,一個是管道的讀取端描述符pipefd[0],另一個是管道的寫入端描述符pipefd[1]。管道沒有文件名與之關聯,因此程序沒有選擇,只能通過文件描述符來訪問管道,只有那些能看到這兩個文件描述符的進程才能夠使用管道。如果進程執行了fork操作,那么管道就變成如下所示:
一般來說管道是單向使用,所以fork之后,新老進程一個會關閉write fd,另一個會關閉read fd,避免讀寫混淆。在shell中執行管道命令就是這種情景,只是略有特殊之處,其特殊的地方是管道描述符占用了標準輸入和標準輸出兩個文件描述符。
單向使用管道,也就是說,如果沒有用到管道的進程應該盡早釋放管道文件fd,這么做不僅僅是為了讓數據的流向更加清晰,也不僅僅是為了節省文件描述符,更重要的原因是:關閉未使用的管道文件描述符對管道的正確使用影響重大。
管道有如下3個特性:
只有當所有的寫入端描述符都已關閉,且管道中的數據都被讀出,對讀取端描述符調用read函數才會返回0(即讀到EOF標志)。
如果所有讀取端描述符都已關閉,此時進程再次往管道里面寫入數據,寫操作會失敗,errno被設置為EPIPE,同時內核會向寫入進程發送一個SIGPIPE的信號。
當所有的讀取端和寫入端都關閉后,管道才能被銷毀。
管道的本質是一片內存區域,默認大小是65536字節,不過可以調用fcntl來獲取和修改這個值的大小。因此在使用管道的過程中要注意寫入數據是否能及時消費的問題,一旦管道滿了,寫入就會被阻塞;對于讀取端,要及時地讀取,防止管道被寫滿,造成寫入阻塞。
上面說的都是常見的管道形式,也就是匿名管道,因為沒有實體文件與之關聯,所以只能在具有親屬關系的進程間使用。因此就出現了另一種管道形式,命名管道,其最大的差別就是有實體文件與之關聯。由于存在實體文件,不相關的沒有親緣關系的進程也可以通過使用FIFO來實現進程之間的通信。
創建命名管道函數如下:
int mkfifo(const char *pathname, modt_t mode)
命名管道支持的管道操作和匿名管道是一樣的,只不過它多了一個關聯文件,有文件名,這樣任何進程通過文件名來使用它而已。
感謝各位的閱讀!關于“Linux管道的示例分析”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。