歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Linux 有名管道(FIFO)

Linux 有名管道(FIFO)

日期:2017/3/1 10:07:46   编辑:Linux編程

無名管道應用的一個重大限制是它沒有名字,因此,只能用於具有親緣關系的進程間通信,在有名管道(named pipe或FIFO)提出後,該限制得到了克服。FIFO不同於管道之處在於它提供一個路徑名與之關聯,以FIFO的文件形式存在於文件系統中。這樣,即使與FIFO的創建進程不存在親緣關系的進程,只要可以訪問該路徑,就能夠彼此通過FIFO相互通信(能夠訪問該路徑的進程以及FIFO的創建進程之間),因此,通過FIFO不相關的進程也能交換數據。值得注意的是,FIFO嚴格遵循先進先出(first in first out),對管道及FIFO的讀總是從開始處返回數據,對它們的寫則把數據添加到末尾。它們不支持諸如lseek()等文件定位操作。

管道的緩沖區是有限的(管道制存在於內存中,在管道創建時,為緩沖區分配一個頁面大小)

管道所傳送的是無格式字節流,這就要求管道的讀出方和寫入方必須事先約定好數據的格式,比如多少字節算作一個消息(或命令、或記錄)等等

FIFO往往都是多個寫進程,一個讀進程。可以參考我這裡的文章 http://www.linuxidc.com/Linux/2012-11/73497.htm

FIFO的打開規則:

1. 如果當前打開操作是為讀而打開FIFO時,若已經有相應進程為寫而打開該FIFO,則當前打開操作將成功返回;否則,可能阻塞直到有相應進程為寫而打開該FIFO(當前打開操作設置了阻塞標志);或者,成功返回(當前打開操作沒有設置阻塞標志)。

2. 如果當前打開操作是為寫而打開FIFO時,如果已經有相應進程為讀而打開該FIFO,則當前打開操作將成功返回;否則,可能阻塞直到有相應進程為讀而打開該FIFO(當前打開操作設置了阻塞標志);或者,返回ENXIO錯誤(當前打開操作沒有設置阻塞標志)。

總之就是一句話,一旦設置了阻塞標志,調用mkfifo建立好之後,那麼管道的兩端讀寫必須分別打開,有任何一方未打開,則在調用open的時候就阻塞。

從FIFO中讀取數據:

約定:如果一個進程為了從FIFO中讀取數據而阻塞打開FIFO,那麼稱該進程內的讀操作為設置了阻塞標志的讀操作。(意思就是我現在要打開一個有名管道來讀數據!)

如果有進程寫打開FIFO,且當前FIFO內沒有數據(可以理解為管道的兩端都建立好了,但是寫端還沒開始寫數據!)

1. 則對於設置了阻塞標志的讀操作來說,將一直阻塞(就是block住了,等待數據。它並不消耗CPU資源,這種進程的同步方式對CPU而言是非常有效率的。)

2. 對於沒有設置阻塞標志讀操作來說則返回-1,當前errno值為EAGAIN,提醒以後再試。

對於設置了阻塞標志的讀操作說(見上面的約定)

造成阻塞的原因有兩種

1. FIFO內有數據,但有其它進程在讀這些數據(對於各個讀進程而言,這根有名管道是臨界資源,大家得互相謙讓,不能一起用。)

2. FIFO內沒有數據。解阻塞的原因則是FIFO中有新的數據寫入,不論信寫入數據量的大小,也不論讀操作請求多少數據量。

讀打開的阻塞標志只對本進程第一個讀操作施加作用,如果本進程內有多個讀操作序列,則在第一個讀操作被喚醒並完成讀操作後,其它將要執行的讀操作將不再阻塞,即使在執行讀操作時,FIFO中沒有數據也一樣,此時,讀操作返回0。

注:如果FIFO中有數據,則設置了阻塞標志的讀操作不會因為FIFO中的字節數小於請求讀的字節數而阻塞,此時,讀操作會返回FIFO中現有的數據量。

Copyright © Linux教程網 All Rights Reserved