Pipe
如何將數據饋送到管道直到它滿了,不多不少?
我想在 Linux 上使用管道作為主程序和從程序之間的同步原語。經典的方法是創建兩個管道,但我相信有一種方法可以使用單個 fd。考慮:
- 從站創建
r
-w
管道。- 讀取端
r
傳遞給主控。- 當從機準備好時,它會寫入
w
N 個字節,然後再寫入 N 個字節,然後是 1 個字節,其中 N 是管道緩衝區大小。第一個write(2)
立即返回,第二個因緩衝區已滿而阻塞。- 主塊並從
r
. 第二個write(2)
返回,第三個write(2)
塊。- 在 master 讀取數據後,它會做它必須做的任何事情。
- 當從機要恢復時,主機再次從
r
. 第三個write(2)
返回,奴隸繼續前進。但是,手冊頁是
fcntl
這樣說的:Changing the capacity of a pipe F_SETPIPE_SZ (int; since Linux 2.6.35) ... Note that because of the way the pages of the pipe buffer are employed when data is written to the pipe, the number of bytes that can be written may be less than the nominal size, depend‐ ing on the size of the writes.
手冊頁似乎說,如果管道緩衝區大小為 N 字節並且我將 M<=N 字節寫入管道,則寫入可能會阻塞。在什麼情況下會發生這種情況(除了管道中已經有很多數據的簡單情況)?
此外,“取決於寫入的大小”聽起來很奇怪。如果我正好寫 N 個字節,我會得到這種奇怪的行為嗎?
我不會依賴這種行為元素。管道旨在成為連續的數據流。讀取和寫入不能輕易相互匹配,您應該依賴的唯一真正保證是第一個字節輸入將是第一個字節輸出。
關於緩衝區分頁的手動註釋的原因是管道依賴於環形緩衝區。從手冊中我可以推斷出“環”是一圈頁面而不是一圈字節。IE:頁面填滿,當頁面已滿時,使用下一頁。頁面在被完全閱讀之前不會被重新使用。這意味著半讀頁面將根本無法用於寫入。 這只是手冊的一個推論,我沒有檢查原始碼。
依賴這種行為的最大問題是它是一個實現細節,而不是管道的預期效果。核心開發人員可能隨時更改此設置,您的程式碼將突然出現競爭條件。