[apue] FIFO:不是文件的文件

衆所周知,FIFO中文譯爲命名管道,是PIPE的升級版。而PIPE是管道,系統提供的一種進程間通信方式,FIFO與PIPE有如下方面不一樣:html

1) FIFO須要先在文件系統建立(mkfifo),以後使用文件接口操做(open/close/read/write);而PIPE不與文件系統相關聯,建立PIPE後直接讀寫(pipe),無需打開;git

2) PIPE只能在父子關係的進程間使用,本質是經過fork複製了母進程空間從而擴展到另外一個進程;而FIFO關聯的各個進程間更爲自由,沒必要由fork產生也可使用。github

 

但他們都是管道,本質上就是內核開闢的一塊緩存區,雖然FIFO在文件系統有一個入口,可是它和文件有很大不一樣,具體體如今使用FIFO的文件接口的幾個限制上:緩存

1) 若是讀進程以只讀方式打開FIFO,若此時尚未寫進程打開FIFO,則讀進程會阻塞在open上,直到有進程以寫方式打開FIFO文件;異步

2) 若是寫進程以只寫方式打開FIFO,若此時尚未讀進程打開FIFO,則寫進程會阻塞在open上,直到有進程以讀方式打開FIFO文件;測試

3) 若是進程以讀寫方式打開FIFO,此時open將再也不阻塞,可是若是此時沒有寫進程向管道內寫數據,則讀取將阻塞在read上,直到有進程寫入數據爲止。(須要注意的是若是以前有進程寫入過數據,可是該進程在本進程open以前已經關閉FIFO,則相應的數據是讀不到的);spa

4) 若是進程以讀寫方式打開FIFO,此時open將再也不阻塞,無論有沒有讀進程從管道讀數據,寫數據(write)都將成功返回,直到底層緩衝區被寫滿;線程

5) 若是進程以只讀且異步方式(O_NONBLOCK)打開FIFO,則不論有沒有寫進程打開FIFO,都不會阻塞在open上。但若是此時沒有寫進程寫入數據,後續read將返回0;code

6) 若是進程以只寫且異步方式(O_NONBLOCK)打開FIFO,若此時尚未讀進程打開FIFO,則open返回-1,errno設置爲ENXIO(6 /* No such device or address */)htm

 

通常不多用讀寫方式打開FIFO,由於那樣很容易讀到本身寫入的數據,除非此FIFO就是用來在進程內部多個線程之間使用的。

能夠看到上面林林總總的各類限制,指向的一個目標就是:保證讀寫進程同時打開FIFO並進行數據交換。換句話說,就是FIFO沒有任何臨時存儲數據的能力,錯過了,就沒了。

從這個意義上說,FIFO根本不是文件。

 

除此以外,FIFO在讀寫進程退出時的表現,也與PIPE類似,而與文件不一樣:

1) 當全部讀進程退出後,寫進程再寫入數據會收到SIGPIPE信號;

2) 當全部寫進程退出後,讀進程再讀取數據read會返回0;

 

對於第1點,特別聲明一下,就是在PIPE中,多對一的狀況與一對一讀寫進程不一樣,當讀進程退出時,多個寫進程並無收到SIGPIPE信號,詳見下面這篇文章:

多進程管道讀寫的一些疑問

 

總之,從各方來講,FIFO都是一個PIPE,而不是一個傳統意義上的文件

測試讀代碼

測試寫代碼

相關文章
相關標籤/搜索