File-Descriptors

當管道中沒有數據並且寫端關閉時,選擇會指示管道是可讀的嗎?

  • June 10, 2020

我正在閱讀Linux 程式介面

來自63.2.3 文件描述符何時準備就緒?, 它說:

正確使用select()poll()需要了解文件描述符指示準備就緒的條件。O_NONBLOCKSUSv3 表示,如果對 I/O 函式的呼叫不會阻塞,則認為 文件描述符(帶有清除)已準備就緒,無論該函式是否實際傳輸數據。重點是斜體:告訴我們一個I/O操作是否不會阻塞,而不是它是否能成功傳輸數據select()poll()有鑑於此,讓我們考慮這些系統呼叫如何針對不同類型的文件描述符進行操作。我們在包含兩列的表格中顯示此資訊:

  • select()列指示文件描述符是否標記為可讀 (r)、可寫 (w) 或具有異常條件 (x)。

….

管道和 FIFO

表 63-4 總結了管道或 FIFO 讀取端的詳細資訊。該Data in pipe?列指示管道是否至少有 1 個字節的數據可供讀取。在此表中,我們假設 POLLINevents欄位中指定了poll()

….

表 63-4:管道或 FIFO 讀取端的select()指示poll()

Condition or event              | select()   | poll()
Data in pipe? | Write end open? |            
no            | no              | r          | POLLHUP
yes           | yes             | r          | POLLIN
yes           | no              | r          | POLLIN | POLLHUP

和表 63-5:select()以及poll()管道或 FIFO 寫結束的指示

(在此表中,我們假設POLLOUT在事件欄位中為poll().)指定。

Condition or event                          | select()   | poll()
Space for PIPE_BUF bytes? | Read end open?  |            
no                        | no              | w          | POLLERR
yes                       | yes             | w          | POLLOUT
yes                       | no              | w          | POLLOUT | POLLERR

我不明白兩個表的第一行情況。

管道中沒有數據,寫結束關閉,select()是否表明它是一個可讀的文件描述符?為什麼?在管道中有數據之前不應該select()阻塞嗎?

沒有PIPE_BUF字節空間,讀取結束關閉,select()將表明作為可寫文件描述符?

假設您打開了管道(讀取端),沒有數據寫入端也打開了。如果您read()在這種情況下執行 a,您將阻止 - 並且select()不會將 FD 報告為可讀。我想我們在這點上是一致的,對吧?

現在假設你在這個阻塞的中間,read()而 writerclose()是他們的管道末端。怎麼了?您的read()回報,結果為0. 如果你在writer sread() 之後呼叫,幾乎會發生同樣的事情。close只有你不會阻止 -read會立即返回,也會有0結果。因此,根據您引用的來源中的推理,您的 FD 是“可讀的” - 或者最好說“不可阻止”,這就是select實際報告的內容。

如果你嘗試編寫一個小例子,你會發現這個定義實際上比你似乎建議的更“直覺”的定義更乾淨、更優雅。

引用自:https://unix.stackexchange.com/questions/591959