Linux下管道使用的一些限制

    在書上和網上翻了翻,管道是單向的、先進先出的,它把一個進程的輸出和另一個進程的輸入連接在一起。一個進程(寫進程)在管道的尾部寫入數據,另一個進程(讀進程)從管道的頭部讀出數據。Linux管道分爲無名管道和命名管道。

一、無名管道pipe

    無名管道具有以下特點:

    1、只能用於具有血緣關係的進程之間,可用於進程或者線程間的通信;
    2、半雙工的通信模式,具有固定的讀端和寫端;
    3、一種特殊的文件,存在於內存中。可通過read、write對其操作。

    pipe使用過程中主要需的限制也是基於以上特點:

    1、兩個進程通過一個無名管道只能實現單向通信(半雙工),父進程寫子進程讀,如果有時候也需要子進程寫父進程讀,就必須另開一個管道。如果只開一個管道,但是父進程不關閉讀端,子進程也不關閉寫端,雙方都有讀端和寫端,是不能實現雙向通信的。

    2、管道的讀寫端通過打開的文件描述符來傳遞,因此要通信的兩個進程必須從它們的公共祖先那裏繼承管道文件描述符。上面的例子是父進程把文件描述符傳給子進程之後父子進程之間通信,也可以父進程fork兩次,把文件描述符傳給兩個子進程,然後兩個子進程之間通信,總之需要通過fork傳遞文件描述符使兩個進程都能訪問同一管道,它們才能通信。

    使用管道需要注意以下4種特殊情況(假設都是阻塞I/O操作,即沒有設置O_NONBLOCK標誌):

    1、如果所有指向管道寫端的文件描述符都關閉了(管道寫端的引用計數等於0),而仍然有進程從管道的讀端讀數據,那麼管道中剩餘的數據都被讀取後,再次read會返回0,就像讀到文件末尾一樣。

    2、如果有指向管道寫端的文件描述符沒關閉(管道寫端的引用計數大於0),而持有管道寫端的進程也沒有向管道中寫數據,這時有進程從管道讀端讀數據,那麼管道中剩餘的數據都被讀取後,再次read會阻塞,直到管道中有數據可讀了纔讀取數據並返回。

    3、如果所有指向管道讀端的文件描述符都關閉了(管道讀端的引用計數等於0),這時有進程向管道的寫端write,那麼該進程會收到信號SIGPIPE,通常會導致進程異常終止。

    4、如果有指向管道讀端的文件描述符沒關閉(管道讀端的引用計數大於0),而持有管道讀端的進程也沒有從管道中讀數據,這時有進程向管道寫端寫數據,那麼在管道被寫滿時再次write會阻塞,直到管道中有空位置了才寫入數據並返回。

二、命名管道fifo

    匿名管道(無名管道pipe)應用的一個限制就是隻能在具有共同祖先(具有親緣關係)的進程間通信。如果我們想在不相關的進程之間交換數據,可以使用FIFO文件來做這項工作,它經常被稱爲命名管道fifo。

    一旦創建了一個FIFO,就可以用open打開它,一般的文件訪問函數(close,read,write)都可以用於FIFO。

    當打開FIFO時,是否設置非阻塞標誌(O_NONBLOCK),將對以後的讀寫產生如下影響:
    1、沒有設置O_NONBLOCK:訪問要求無法滿足時進程阻塞。如讀取空的FIFO時,或者寫入FIFO已滿時;
    2、設置了O_NONBLOCK:訪問要求無法滿足時不阻塞,立即出錯返回,error是ENXIO。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章