原文地址: FIFO有時被稱為命名管道。管道只能由相關進程使用,這些相關進程的共同祖先進程創建了管道。但是,通過FIFO,不相關的進程也能交換數據。
FIFO是一種文件類型(參考)。stat結構()成員的編碼指明文件是否是FIFO類型。可以用()宏對此進行測試。
創建FIFO類似于創建文件。確實,FIFO的路徑名存在于文件系統中。
#includeint mkfifo(const char *pathname, mode_t mode); 返回值:若成功則返回0,若出錯則返回-1
函數中mode參數的規格說明與open函數中的mode相同(見,具體的mode取值見)。新FIFO的用戶和組的所有權規則與中所述的相同。
一旦已經用創建了一個FIFO,就可用open打開它。其實,一般的文件I/O函數(close、read、write、等)都可用于FIFO。
應用程序可以用mknod函數創建FIFO。POSIX.1原先并沒有包括mknod函數,它首先提出了。mknod現在已包括在XSI擴展中。在大多數系統中,調用mknod創建FIFO。
POSIX.1也包括了對(1)命令的支持。于是,用一條shell命令就可以創建一個FIFO,然后用一般的shell I/O重定向對其進行訪問。
當打開一個FIFO時,非阻塞標志()產生下列影響:
類似于管道,若用write寫一個尚無進程為讀而打開的FIFO,則產生信號。若某個FIFO的最后一個寫進程關閉了該FIFO,則將為該FIFO的讀進程產生一個文件結束標志。
一個給定的FIFO有多個寫進程是很常見的。這就意味著如果不希望多個進程所寫的數據互相穿插,則需考慮原子寫操作。正如對于管道一樣,常量說明了可被原子地寫到FIFO的最大數據量。
FIFO有下面兩種用途:
(1)FIFO由shell命令使用以便將數據從一條管道線傳送到另一條,為此無需創建中間臨時文件。
(2)FIFO用于客戶進程-服務器進程應用程序中,以在客戶進程和服務器進程之間傳送數據。
我們各用一個例子來說明這兩種用途。
實例:用FIFO復制輸出流
FIFO可被用于復制串行管道命令之間的輸出流,于是也就不需要寫數據到中間磁盤文件中(類似于使用管道以避免中間磁盤文件)。管道只能用于進程間的線性連接,然而,因為FIFO具有名字,所以它可用于非線性連接。
考慮這樣一個操作過程,它需要對一個經過過濾的輸入流進行兩次處理。圖15-9表示了這種安排。
圖15-9 對一個經過過濾的輸入流進行兩次處理
使用FIFO以及UNIX系統程序tee(1),就可以實現這樣的過程而無需使用臨時文件。(tee程序將其標準輸入同時復制到其標準輸出以及其命令行中包含的命名文件中。)
mkfifo fifo1 prog3 < fifo1 & prog1 < infile | tee fifo1 | prog2
我們創建FIFO,然后在后臺啟動prog3,它從FIFO讀數據。然后啟動prog1,用tee將其輸出發送到FIFO和prog2。圖15-10顯示了這種安排。
圖15-10 使用FIFO和tee將一個流發送到兩個進程
實例:客戶進程-服務器進程使用FIFO進行通信
FIFO的另一個應用是在客戶進程和服務器進程之間傳送數據。如果有一個服務器進程,它與很多客戶進程有關,則每個客戶進程都可將其請求寫到一個該服務器進程創建的眾所周知的FIFO中(“眾所周知”的意思是:所有需要與服務器進程聯系的客戶進程都知道該FIFO的路徑名)。圖15-11顯示了這種安排。因為對于該FIFO有多個寫進程,客戶進程發送給服務器進程的請求其長度要小于字節。這就能避免客戶多個write之間的交錯()。
圖15-11 客戶進程用FIFO向服務器進程發送請求
在這種類型的客戶進程-服務器進程通信中使用FIFO的問題是:服務器進程如何將回答送回各個客戶進程。不能使用單個FIFO,因為服務器進程會發出對各個客戶進程請求的響應,而請求者卻不可能知道什么時候去讀才能恰如其分地讀到對它的響應。一種解決方法是每個客戶進程都在其請求中包含它的進程ID。然后服務器進程為每個客戶進程創建一個FIFO,所使用的路徑名是以客戶進程的進程ID為基礎的。例如,服務器進程可以用名字/tmp/serv1.XXXXX創建FIFO,其中XXXXX被替換成客戶進程的進程ID。圖15-12顯示了這種安排。
圖15-12 客戶進程-服務器進程用FIFO進行通信
這種安排可以工作,但也有一些不足之處。其中之一是服務器進程不能判斷一個客戶進程是否崩潰終止對進程之間信息的復制,這就使得客戶進程專用的FIFO會遺留在文件系統中。另一個不足之處是服務器進程必須捕捉信號對進程之間信息的復制,因為客戶進程在發送一個請求后沒有讀取響應就可能終止,于是留下一個只有寫進程(服務器進程)而無讀進程的客戶進程專用FIFO。
按照圖15-12中的安排,如果服務器進程以只讀方式打開眾所周知的FIFO(因為它只需讀該FIFO),則每當客戶進程數從1變成0時,服務器進程就將在FIFO中讀到一個文件結束標記。為使服務器進程免于處理這種情況,一種常用的技巧是使服務器進程以讀-寫方式打開其FIFO。
社區發起?晨讀計劃?,每天堅持積累一點,今天的努力至少讓我們比昨天更進一步。
?晨讀計劃? 期待你的加入... ...
:基于的高性能Web應用開發框架