2009-12-27 44 views
13

很明顯,read(2)系統調用通常返回的字節數少於要求讀取的字節數。但是,不少程序假定在使用本地文件時,讀取(2)永遠不會返回比所要求的更少的內容(當然,除非文件更短)。因此,我的問題是:在Linux上,在哪些情況下可以讀取(2)返回小於所請求的內容,如果從打開的文件中讀取並且沒有遇到EOF並且讀取的數量最多隻有幾千字節?從文件系統「短暫讀取」,什麼時候可以發生?

一些猜測:

  • 能收到信號中斷這樣讀,但不能讓它失敗?
  • 不同的文件系統會影響這種行爲嗎? jffs2有什麼特別的嗎?
+0

什麼程序「假設在使用本地文件時,read(2)永遠不會返回小於要求的內容?在一般情況下,這聽起來像一個錯誤。 – Ken 2009-12-27 01:25:45

+0

例如,klibc utils中的fstype binary。似乎很多低級程序可以假定與文件一起工作,直接假定讀取從不短。 – Nakedible 2009-12-27 16:05:12

回答

13

POSIX.1-2008 states

返回可小於 nbyte如果留在 文件的字節數小於nbyte,如果 讀()請求是值被一個 信號中斷,或者如果該文件是一個管道或者 FIFO或特殊文件並且具有較少 比nbyte字節立即可用 閱讀。

基於磁盤的文件系統通常使用不間斷讀取,這意味着讀取操作通常不會被信號中斷。基於網絡的 文件系統有時使用可中斷讀取,這可以返回部分數據或無數據。 (在NFS的情況下,可以使用intr安裝選項進行配置。) 它們有時也會實現超時。請注意,即使/ some /任意/文件/路徑可能指向一個FIFO或 特殊文件,所以您認爲是一個普通文件可能不是。因此,即使它們不太可能,也是處理部分讀取的良好實踐。

+1

謝謝。如果這是正確的,那麼我們有更多的調試要做。 我們正在jffs2文件系統上得到一個確認的簡短閱讀(我猜不應該有可中斷的閱讀),而且該文件絕對是一個常規文件。這種情況每年至多發生一次,所以重現性很低。 – Nakedible 2009-12-27 15:48:22

+1

讀取一個數據塊後,文件系統被允許中斷讀取自身。 – Joshua 2011-08-08 21:29:31

1

接收到的信號只會在read()失敗,如果它還沒有讀取一個字節。否則,它將返回部分數據。

我猜在其他情況下,備用文件系統可能確實會返回短讀。例如,對於我來說,讓基於網絡的文件系統像網絡套接字一樣具有短讀取(通常具有它們)是有道理的。

+0

謝謝,這很有幫助!雖然關於可中斷和不間斷文件系統的信息更有幫助。 – Nakedible 2009-12-27 15:53:52

3

我不得不問:「你爲什麼關心這個原因」?如果read可以返回少於請求數量的字節數(正如你所指出的那樣,它當然可以)爲什麼你不想處理這種情況?

+0

要添加,無論如何你都要檢查數據 - 所以如果它很短,你會立即知道。否則,閱讀的原因是什麼? – 2009-12-27 01:13:48

+9

尼爾,我不禁要問:爲什麼你在乎他爲什麼想知道這會發生?即使他處理了這種情況,也知道它會如何發生,例如,以便他可以嘗試它並測試他的代碼是否按預期處理它。如果不是他自己的個人代碼不處理這種情況下,這些信息將作爲指示的一部分,需要重現任何錯誤報告或補丁提交伴隨的問題。 – mark4o 2009-12-27 06:49:21

+0

我問的原因是,我們看到這種行爲在數千個系統的安裝基礎上,我們需要儘可能準確地進行評估,從長遠來看,這個問題可能會有多普遍。 瞭解如何或爲何發生是調查的一部分。 – Nakedible 2009-12-27 15:50:20

1

如果它實際上是一個您正在閱讀的文件,那麼您可以在文件結束之前讀取最後一次讀取。

不管怎樣,通常最好表現得好像任何讀取都可以是簡短的讀取。如果您正在讀取的是管道或輸入設備(stdin)而不是文件,則只要您的緩衝區大於當前輸入緩衝區中的內容,就可以進行簡短讀取。

+0

我的意思是沒有遇到EOF就是它不是在文件結尾之前的最後一次讀取。此外,有問題的文件是一個常規文件。 – Nakedible 2009-12-27 15:51:48

0

我不確定,但當操作系統用完頁面緩存中的頁面時,可能會出現這種情況。你可以建議在這種情況下調用刷新線程,但它取決於I/O調度程序中使用的啓發式。這種情況可能會導致讀取返回更少的字節。