2012-03-07 65 views
4

我看到許多文章建議不要將大文件映射爲mmap文件,以便虛擬地址空間不會僅由mmap進行。使用內存映射文件讀取大文件

這是怎麼改變的地址空間顯着增加的64位進程? 如果我需要隨機訪問一個文件,是否有理由不一次映射整個文件? (幾十個GB文件)

回答

2

有一點需要注意的是,映射創建時內存映射需要大量連續的(虛擬)內存塊;在32位系統上,這特別吸引人,因爲在加載的系統上,不太可能長時間連續運行ram,映射將失敗。在64位系統上這很容易,因爲64位的上限是巨大的。

如果您在受控環境中運行代碼(例如您正在構建自己並知道運行此代碼的64位服務器環境),請繼續並映射整個文件並進行處理。

如果您要編寫通用代碼,該代碼可以運行在任意數量的配置類型的軟件上,那麼您需要遵循更小的分塊映射策略。例如,將大文件映射到1GB塊的集合,並具有抽象層,該抽象層執行讀取(偏移)等操作,並在執行操作之前將它們轉換爲右塊中的偏移量。

希望有所幫助。

4

即使在64位平臺上(虛擬地址空間大小不成問題),使用內存映射文件也是有原因的。它涉及(潛在的)錯誤處理。

當「常規」讀取文件時 - 任何I/O錯誤都由相應的函數返回值報告。其餘的錯誤處理由您決定。

OTOH如果在隱式I/O期間出現錯誤(由於頁面錯誤並嘗試將所需文件部分加載到適當的內存頁面中) - 錯誤處理機制取決於OS。

在Windows中,通過SEH執行錯誤處理 - 所謂的「結構化異常處理」。異常傳播到用戶模式(應用程序的代碼),您有機會正確處理它。正確的處理要求您在編譯器中編譯適當的異常處理設置(以保證調用析構函數,如果適用的話)。

我不知道如何在unix/linux中執行錯誤處理。

P.S.我不說不要使用內存映射文件。我說這樣做要小心

+1

完全相同的論點適用於讀取任何內存 – 2012-03-07 21:38:17

+3

@David Heffernan:不完全,這取決於你準確讀什麼。如果加載程序代碼或數據時出現錯誤(全局,堆棧/ tls或堆),則只會終止該進程。操作系統沒有給予應用程序處理這個問題的機會,因爲應用程序已經「損壞」了。由應用程序自己創建的內存映射文件產生的OTOH錯誤 - 具有更多機會正確處理 – valdo 2012-03-07 21:43:28

+0

因此,您說內存映射文件的錯誤與讀取啞指針有區別嗎?無論如何,我無法看到你的答案與問題的相關性。即使它是合理的建議,它與所提問題是正交的。 – 2012-03-07 21:46:09

6

在64位上,繼續並映射文件。

基於Linux體驗,需要考慮的一件事是:如果訪問是真正隨機的,並且文件比您期望在RAM中緩存更大(因此再次訪問頁面的機會很小),那麼它可以是值得指定MADV_RANDOMmadvise來穩定地停止命中文件頁面的積累,毫無意義地將其他實際有用的東西交換出去。不知道windows equivalent API是什麼。