進程間通信——命名管道

   前面介紹的管道屬於匿名管道,只能夠用於有血緣關係的進程間通信,比如父子進程之間的通信。下面主要討論另一種管道——命名管道。

    在命名管道(named pipe或FIFO)提出後,該限制得到了克服。FIFO不同於管道之處在於它提供一個路徑名與之關聯,以FIFO的文件形式存儲於文件系統中。命名管道是一個設備文件,因此,即使進程與創建FIFO的進程不存在親緣關係,只要可以訪問該路徑,就能夠通過FIFO相互通信。同時,FIFO(first input first output)總是按照先進先出的原則工作,第一個被寫入的數據將首先從管道中讀出。


【命名管道的創建和讀寫】

     命名管道的創建有兩種方式:一是Shell下交互一個命名管道;二是在程序中使用系統函數建立命名管道。

    Shell方式下創建命名管道的系統函數有兩個:mknod和mkfifo

頭文件:                                                                                                          頭文件:

       #incldue<sys/types.h>                                                                                     #incldue<sys/types.h>

       #include<sys/stat.h>                                                                                        #include<sys/stat.h>

       #include<fcntl.h>                                                                                                         

       int mknod(const char* path,mode_t mod,dev_t dev);                                     int mkfifo(const char* path,mode_t mode);

       這兩個函數調用成功都返回0,失敗都返回-1.

       mknod和mkfifo這兩個函數都能創建一個FIFO文件,注意是創建一個真實存在於文件系統中的文件,path指定了文件名,而mode爲創建的命名管道的模式,則指定了文件的讀寫權限。dev爲設備值,該值取決於文件創建的種類,它只在創建設備文件時纔會用到。

       mkfifo函數的作用是在文件系統中創建一個文件,該文件用於提供FIFO功能,即命名管道。 前邊講的那些管道都沒有名字,因此它們被稱爲匿名管道,或簡稱管道。對文件系統來說, 匿名管道是不可見的,它的作用僅限於在父進程和子進程兩個進程間進行通信。而命名管道是一個可見的文件,因此,它可以用於任何兩個進程之間的通信,不管這兩個進程是不 是父子進程,也不管這兩個進程之間有沒有關係。


例:下面實現兩個進程通過命名管道進行通信:

                     

運行結果:

read端:                                                                                                                                              write端:

                                                                                


      其中,read端中的“0666|S_IFIFO”指明創建一個命名管道且存取權限爲0666,即就是創建者、與創建者同組的用戶、其他用戶對該命名管道的訪問權限都是讀和寫。 命名管道創建後就可以使用了,其使用方法和管道基本是相同的。只是使用命名管道時,必須先調用open()函數將其打開。因爲命名管道是存儲於內存中的特殊文件。調用open()打開命名管道的進程可能會被阻塞,但如果同時用讀寫方式 (O_RDWR)打開,則一定不會導致阻塞;如果以只讀方式(O_RDONLY)打開,則調用open()函數的進程將會被阻塞直到有寫入數據的一方打開管道;同樣以寫方式(O_WRONLY)打開 也會阻塞直到有讀取數據的一方打開管道。


【管道的實現機制和管道的容量】

      管道在進程間通信中是比較常用的,其實管道就是一種特殊的文件。

      (1)管道的大小

              管道是一個固定大小的緩衝區。Linux中該緩衝區的大小爲1頁,即4K字節,所以在寫管道時可能變滿,當這種情況發生時,隨後對管道write()調用將默認地被阻塞,等待某些數據被讀取,以便騰出足夠的空間供write()調用寫。

      (2)讀進程工作較寫進程快

               當所有當前進程數據已被讀取時,管道變空。當這種情況發生時,一個隨後的read()調用將默認地被阻塞,等待某些數據被寫入,這解決了read()調用返回文件結束的問題。

       (3)管道讀數據是一次性的

               數據一旦被讀,就會從管道中被拋棄,釋放空間以便寫更多的數據。


例:查看管道容量


運行結果:






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