管道 FIFO注意事項

2021-10-09 13:19:35 字數 2554 閱讀 4145

管道

1. 其本質是乙個偽檔案(實為核心緩衝區)

2. 由兩個檔案描述符引用,乙個表示讀端,乙個表示寫端。

3. 規定資料從管道的寫端流入管道,從讀端流出。

管道的原理: 管道實為核心使用環形佇列機制,借助核心緩衝區(4k)實現。

管道的侷限性:

資料一旦被讀走,便不在管道中存在,不可反覆讀取。

緩衝區是有限

由於管道採用半雙工通訊方式。因此,資料只能在乙個方向上流動。

只能在有公共祖先的程序間使用管道。

所傳送的是無格式位元組流

關閉未使用的管道檔案描述符不僅僅是為了確保程序不會耗盡其檔案描述符的限制——-這對於正確使用管道是非常重要的。 

使用管道需要注意以下4種特殊情況(假設都是阻塞i/o操作,沒有設定o_nonblock標誌):

1. 如果所有指向管道寫端的檔案描述符都關閉了(管道寫端引用計數為0),而仍然有程序從管道的讀端讀資料,那麼管道中剩餘的資料都被讀取後,再次read會返回0,就像讀到檔案末尾一樣。

2. 如果有指向管道寫端的檔案描述符沒關閉(管道寫端引用計數大於0),而持有管道寫端的程序也沒有向管道中寫資料,這時有程序從管道讀端讀資料,那麼管道中剩餘的資料都被讀取後,再次read會阻塞,直到管道中有資料可讀了才讀取資料並返回。

3. 如果所有指向管道讀端的檔案描述符都關閉了(管道讀端引用計數為0),這時有程序向管道的寫端write,那麼該程序會收到訊號sigpipe,通常會導致程序異常終止。當然也可以對sigpipe訊號實施捕捉,不終止程序。具體方法訊號章節詳細介紹。

4. 如果有指向管道讀端的檔案描述符沒關閉(管道讀端引用計數大於0),而持有管道讀端的程序也沒有從管道中讀資料,這時有程序向管道寫端寫資料,那麼在管道被寫滿時再次write會阻塞,直到管道中有空位置了才寫入資料並返回。

管道在它的引用計數(訪問同乙個管道的開啟著的描述符的個數)為0後消失。

fifo

用mkfifo函式建立乙個命名管道,若已存在則返回錯誤。

函式引數中,第乙個為檔案的相對路徑或絕對路徑,表明在系統中建立乙個管道檔案,第二個引數為檔案的許可權資訊。

建立好管道檔案之後,就可以使用了,因為是檔案,所以可以開啟,在乙個程式中開啟檔案,如果以讀寫方式開啟就不會阻塞,如果以唯讀方式開啟就會阻塞直到有以寫方式開啟此檔案為止,同樣,如果以只寫方式開啟就會阻塞直到有讀方式開啟檔案為止。   (o_rdwr mode 開啟會繞開 fifo 的阻塞行為, 因為其不具有可移植性,開發人員應該避免使用, 而是應該是用o_nonblock的方式進行,所以書上是寫只能  唯讀  或者只寫)

linux 預設read/write操作是阻塞的, 可以在開啟的時候設定o_nonblock為非阻塞(或者之後使用 fcntl 函式進行設定)。

核心為管道維護了乙個訪問計數, 統計開啟檔案描述符的個數, 呼叫了unlink 函式後, 如果計數不為0, 不會直接刪除,會等到最後乙個 close 呼叫使得計數為0, 才呼叫刪除 fifo, 如果沒有呼叫 unlink, 即使計數為0, 也不會刪除fifo。

但是當管道最後乙個開啟的檔案描述符被關閉,其中的資料被丟棄。刪除fifo是指刪除這個路徑名。unlink是會直接刪除這個路徑名,但是仍開啟著的描述符不受影響。

實際上fifo的路徑名也會使得引用計數+1,因此上面那段文字就很好理解了。

開啟的時候要小心順序,可能會造成死鎖。dos型攻擊就是依靠這個原理的。

在設定管道檔案的許可權時,需要考慮umask的影響。

fifo是一種只能在單台主機上使用的ipc模式,

請求讀出的大小大於當前可用大小時,則只返回可用的資料。

請求寫入大小小於或等於 pipe_buf時,write保證是原子的。如果大於,則不保證原子。

如果設定了o_nonblock

待寫的位元組數小於等於pipe_buf:

如果管道或fifo中沒有足以存放所有請求位元組數的空間,那麼立即返回乙個eagain錯誤。(因為保證不了原子性,所以返回錯誤)

待寫的位元組數大於pipe_buf

如果管道或fifo中至少有1位元組。那麼寫入能容納的位元組,同時把位元組數作為返回值。(因為不需要保證原子性,所以直接寫入就行)

如果管道或fifo已滿,則立即返回乙個eagain錯誤。

如果向乙個沒有為讀開啟著的管道或fifo寫入,則核心產生乙個sigpipe訊號。該訊號預設是終止程序

如果向乙個沒有為寫開啟著的管道或fifo讀入,則要麼阻塞(等待寫描述符且等待寫入),要麼返回eof(原本的寫描述符關閉了),如果再有寫的描述符開啟,則繼續阻塞。

所以有個技巧就是,伺服器的寫描述符不關閉。這樣當客戶端close之後就不會出現服務端read到0,然後被迫重開啟fifo阻塞到read。如果伺服器的寫描述符不關閉,則客戶端都close之後,read會阻塞直到來了新的客戶端。

管道及fifo限制

open_max 乙個程序在任意時刻能開啟的最大描述符數

pipe_bug 可原子地寫往乙個管道或fifo的最大資料量

他們都是資料流,資料流,流。類似socket的東西

非同步FIFO設計注意事項

近日學習用到非同步fifo,故寫下這篇部落格記錄學習心得。在我看來,非同步fifo的設計注意事項大體分為兩點 亞穩態的處理 空滿狀態的判斷 第一,來說一下亞穩態。亞穩態是指觸發器無法在某個規定時間內達到乙個可確認的狀態。在fifo的設計中,產生的原因主要由兩點 一是邏輯電平的誤判,也就是如果通過二進...

非同步FIFO設計的一些注意事項

非同步fifo的結構基本上是是按照下面的思路來設計 1.讀寫的指標分別用gray code sync到另外乙個clock domain,sync的時候至少打2拍。2.讀寫指標最高位各加乙個bit用來判斷空和慢,對於fifo來說,永遠是讀指標追寫指標,當指標相同的時候,用加的這個最高bit來 判斷是誰...

java DOM 注意事項

1.w3c把標籤內的文字部分也定義成乙個node 2.element物件代表的是xml文件中的標籤元素 繼承於node,亦是node的最主要的子物件 3.attr實際上是包含在element中的,它並不能被看作是element的子物件,因而在dom中attr並不是dom樹的一部分,所以node中的 ...