IPC安全
前面總結了匿名管道,如今來看命名管道:因爲匿名管道的一個限制就是:只能是有血緣關係的進程間才能夠通訊,好比:有兩個同祖先的子進程,父子進程等;爲了突破這一個限制,想讓沒有任何關係的兩個進程間也能正常通訊,因此就就有了命名管道這樣的一個通訊機制,一塊兒來看看:函數
命名管道spa
1、原理:code
管道的一個不足之處是沒有名字,所以,只能用於具備親緣關係的進程間通訊,在命名管道(named pip或FIFO)提出後,該限制獲得了克服。FIFO不一樣於管道之處在於它提供一個路徑名與之關聯,以FIFO的文件形式存儲於文件系統中。命名管道是一個設備文件,所以,即便進程與建立FIFO的進程不存在親緣關係,只要能夠訪問該路徑,就可以經過FIFO相互通訊。blog
值得注意的是,FIFO(first input first output)老是按照先進先出的原則工做,第一個被寫入的數據將首先從管道中讀出。進程
Linux下有兩種方式建立命名管道。一是在Shell下交互地創建一個命名管道,二是在程序中使用系統函數創建命名管道。Shell方式下可以使用mknod或mkfifo命令,下面命令使用 mknod建立了一個命名管道: ip
mknod namedpipe
建立命名管道的系統函數有兩個:mknod和mkfifo。兩個函數均定義在頭⽂文件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建立命名管道:
「S_IFIFO|0666」指明建立一個命名管道且存取權限爲0666,即建立者、與建立者同組的用戶、其餘用戶對該命名管道的訪問權限都是可讀可寫。
命名管道建立後就可使用了,命名管道和管道的使用方法基本是相同的。只是使用命名管道時,必須用open()將其打開。由於命名管道是一個存在於硬盤上的文件,而管道是存在於內存中的特殊文件。
須要注意的是,調用open()打開命名管道的進程可能會被阻塞。但若是同時用讀寫方式(O_RDWR)打開,則必定不會致使阻塞;若是以只讀方式(O_RDONLY)打開,則調用open()函數的進程將會被阻塞直到有寫方打開管道;一樣以寫方式(O_WRONLY)打開也會阻塞直到有讀方式打開管道。
四:結束
文件系統中的路徑名是全局的,各進程均可以訪問,所以能夠用文件系統中的路徑名來標識一個IPC通道。 命名管道也被稱爲FIFO文件,它是一種特殊類型的文件,它在文件系統中以文件名的形式存在,可是它的行爲卻和以前所講的沒有名字的管道(匿名管道)相似。
因爲Linux中全部的事物均可被視爲文件,因此對命名管道的使用也就變得與文件操做很是的統一,也使它的使用很是方便,同時咱們也能夠像日常的文件名同樣在命令中使用。
前面的例子兩個進程之間的通訊問題,也就是說,一個進程向FIFO文件寫數據,而另外一個進程則在FIFO文件中讀取數據。試想這樣一個問題,只使用一個FIFO文件,若是有多個進程同時向同一個FIFO文件寫數據,而只有一個讀FIFO進程在同一個FIFO文件中讀取數據時,會發生怎麼樣的狀況呢,會發生數據塊的相互交錯是很正常的?並且我的認爲多個不一樣進程向一個FIFO讀進程發送數據是很普通的狀況。
爲了解決這一問題,就是讓寫操做的原子化。怎樣才能使寫操做原子化呢?答案很簡單,系統規定:在一個以O_WRONLY(即阻塞方式)打開的FIFO中, 若是寫入的數據長度小於等待PIPE_BUF,那麼或者寫入所有字節,或者一個字節都不寫入。若是全部的寫請求都是發往一個阻塞的FIFO的,而且每一個寫記請求的數據長度小於等於PIPE_BUF字節,系統就能夠確保數據決不會交錯在一塊兒。
命名管道總結到此,其他通訊機制,見下一篇博文。
賜教!