有名管道的開啟規則
有名管道比管道多了一個開啟操作:open。
FIFO的開啟規則:
如果當前開啟操作是為讀而開啟FIFO時,若已經有相應進程為寫而開啟該FIFO,則當前開啟操作將成功返回;否則,可能阻塞直到有相應進程為寫而開啟該FIFO(當前開啟操作設定了阻塞標誌);或者,成功返回(當前開啟操作沒有設定阻塞標誌)。
如果當前開啟操作是為寫而開啟FIFO時,如果已經有相應進程為讀而開啟該FIFO,則當前開啟操作將成功返回;否則,可能阻塞直到有相應進程為讀而開啟該FIFO(當前開啟操作設定了阻塞標誌);或者,返回ENXIO錯誤(當前開啟操作沒有設定阻塞標誌)。
注意:
讀取管道開啟時需要等待寫入管道的開啟,同時寫入開啟管道又需要等待讀取管道的開啟
Deadlock不會產生,因為這裡“等待”的*不*是另一方的open是否*已經完成*
舉個例子,
如果open FIFO時都不指定O_NONBLOCK, A進程首先 open FIFO for reading, 它會block.
然後B進程 open FIFO for writing, 由於進程A正在open for reading, 因此B的open操作會
立即返回,然後A的open 操作返回。
對開啟規則的驗證參見附2。
2.4有名管道的讀寫規則
從FIFO中讀取資料:
約定:如果一個進程為了從FIFO中讀取資料而阻塞開啟FIFO,那麼稱該進程內的讀操作為設定了阻塞標誌的讀操作。
- 如果有進程寫開啟FIFO,且當前FIFO內沒有資料,則對於設定了阻塞標誌的讀操作來說,將一直阻塞。對於沒有設定阻塞標誌讀操作來說則返回-1,當前errno值為EAGAIN,提醒以後再試。
- 對於設定了阻塞標誌的讀操作說,造成阻塞的原因有兩種:當前FIFO內有資料,但有其它進程在讀這些資料;另外就是FIFO內沒有資料。解阻塞的原因則是FIFO中有新的資料寫入,不論信寫入資料量的大小,也不論讀操作請求多少資料量。
- 讀開啟的阻塞標誌只對本進程第一個讀操作施加作用,如果本進程內有多個讀操作序列,則在第一個讀操作被喚醒並完成讀操作後,其它將要執行的讀操作將不再阻塞,即使在執行讀操作時,FIFO中沒有資料也一樣(此時,讀操作返回0)。
- 如果沒有進程寫開啟FIFO,則設定了阻塞標誌的讀操作會阻塞。
註:如果FIFO中有資料,則設定了阻塞標誌的讀操作不會因為FIFO中的位元組數小於請求讀的位元組數而阻塞,此時,讀操作會返回FIFO中現有的資料量。
向FIFO中寫入資料:
約定:如果一個進程為了向FIFO中寫入資料而阻塞開啟FIFO,那麼稱該進程內的寫操作為設定了阻塞標誌的寫操作。
對於設定了阻塞標誌的寫操作:
- 當要寫入的資料量不大於PIPE_BUF時,linux將保證寫入的原子性。如果此時管道空閑緩衝區不足以容納要寫入的位元組數,則進入睡眠,直到當緩衝區中能夠容納要寫入的位元組數時,才開始進行一次性寫操作。
- 當要寫入的資料量大於PIPE_BUF時,linux將不再保證寫入的原子性。FIFO緩衝區一有空閑地區,寫進程就會試圖向管道寫入資料,寫操作在寫完所有請求寫的資料後返回。
對於沒有設定阻塞標誌的寫操作:
- 當要寫入的資料量大於PIPE_BUF時,linux將不再保證寫入的原子性。在寫滿所有FIFO空閑緩衝區後,寫操作返回。
- 當要寫入的資料量不大於PIPE_BUF時,linux將保證寫入的原子性。如果當前FIFO空閑緩衝區能夠容納請求寫入的位元組數,寫完後成功返回;如果當前FIFO空閑緩衝區不能夠容納請求寫入的位元組數,則返回EAGAIN錯誤,提醒以後再寫;