Linux進程間通訊--命名管道

IPC安全

前面總結了匿名管道,如今來看命名管道:因爲匿名管道的一個限制就是:只能是有血緣關係的進程間才能夠通訊,好比:有兩個同祖先的子進程,父子進程等;爲了突破這一個限制,想讓沒有任何關係的兩個進程間也能正常通訊,因此就就有了命名管道這樣的一個通訊機制,一塊兒來看看:函數

命名管道spa

1、原理:code

       管道的一個不足之處是沒有名字,所以,只能用於具備親緣關係的進程間通訊,在命名管道(named pipFIFO)提出後,該限制獲得了克服。FIFO不一樣於管道之處在於它提供一個路徑名與之關聯,以FIFO的文件形式存儲於文件系統中。命名管道是一個設備文件,所以,即便進程與建立FIFO的進程不存在親緣關係,只要能夠訪問該路徑,就可以經過FIFO相互通訊。blog

值得注意的是,FIFO(first input first output)老是按照先進先出的原則工做,第一個被寫入的數據將首先從管道中讀出。進程

2、命名管道的建立與讀寫

       Linux下有兩種方式建立命名管道。一是在Shell下交互地創建一個命名管道,二是在程序中使用系統函數創建命名管道。Shell方式下可以使用mknodmkfifo命令,下面命令使用 mknod建立了一個命名管道: ip

mknod namedpipe

        建立命名管道的系統函數有兩個:mknodmkfifo。兩個函數均定義在頭⽂文件sys/stat.h內存

        函數原型以下:input

#include <sys/types.h>
#include <sys/stat.h>
int mknod(const char *path,mode_t mod,dev_t dev);
int mkfifo(const char *path,mode_t mode);

        函數mknod參數中path爲建立的命名管道的全路徑名:mod爲建立的命名管道的模式,指明其存取權限;dev爲設備值,該值取決於文件建立的種類,它只在建立設備文件時纔會用到。這兩個函數調用成功都返回0,失敗都返回-1原型

3、實例

用mkfifo建立命名管道:


其中_PATH_是文件路徑名的宏定義:以下:


      「S_IFIFO|0666」指明建立一個命名管道且存取權限爲0666,即建立者、與建立者同組的用戶、其餘用戶對該命名管道的訪問權限都是可讀可寫

      命名管道建立後就可使用了,命名管道和管道的使用方法基本是相同的。只是使用命名管道時,必須用open()將其打開。由於命名管道是一個存在於硬盤上的文件,而管道是存在於內存中的特殊文件。

      須要注意的是,調用open()打開命名管道的進程可能會被阻塞。但若是同時用讀寫方式O_RDWR)打開,則必定不會致使阻塞;若是以只讀方式(O_RDONLY)打開,則調用open()函數的進程將會被阻塞直到有寫方打開管道;一樣以寫方式(O_WRONLY)打開也會阻塞直到有讀方式打開管道。

四:結束

文件系統中的路徑名是全局的,各進程均可以訪問,所以能夠用文件系統中的路徑名來標識一個IPC通道。 命名管道也被稱爲FIFO文件,它是一種特殊類型的文件,它在文件系統中以文件名的形式存在,可是它的行爲卻和以前所講的沒有名字的管道(匿名管道)相似。

因爲Linux中全部的事物均可被視爲文件,因此對命名管道的使用也就變得與文件操做很是的統一,也使它的使用很是方便,同時咱們也能夠像日常的文件名同樣在命令中使用。

5、命名管道的安全問題

   前面的例子兩個進程之間的通訊問題,也就是說,一個進程向FIFO文件寫數據,而另外一個進程則在FIFO文件中讀取數據。試想這樣一個問題,只使用一個FIFO文件,若是有多個進程同時向同一個FIFO文件寫數據,而只有一個讀FIFO進程在同一個FIFO文件中讀取數據時,會發生怎麼樣的狀況呢,會發生數據塊的相互交錯是很正常的?並且我的認爲多個不一樣進程向一個FIFO讀進程發送數據是很普通的狀況。
   爲了解決這一問題,就是讓寫操做的原子化。怎樣才能使寫操做原子化呢?答案很簡單,系統規定:在一個以O_WRONLY(即阻塞方式)打開的FIFO中, 若是寫入的數據長度小於等待PIPE_BUF,那麼或者寫入所有字節,或者一個字節都不寫入。若是全部的寫請求都是發往一個阻塞的FIFO的,而且每一個寫記請求的數據長度小於等於PIPE_BUF字節,系統就能夠確保數據決不會交錯在一塊兒。

命名管道總結到此,其他通訊機制,見下一篇博文。

賜教!

相關文章
相關標籤/搜索