2012-04-24 34 views
2

在我們的應用程序中,我們必須能夠將多個(即最多4個)文件映射到內存中(通過mapViewOfFile)。很長時間以來,這並不是一個問題,但隨着文件在過去幾年越來越大,現在內存碎片阻礙了我們映射這些大文件(文件大小約爲200 MB)。如果當前沒有加載其他文件,則問題可能已經存在。將幾個大文件映射到內存中

我現在正在尋找一種方法確保映射始終成功。因此,我希望在程序啓動時僅爲映射保留一塊內存,因此碎片的影響會更小。

我的第一種方法是HeapCreate私有堆,然後,我會HeapAlloc的內存足以容納映射爲一個文件,然後使用MapViewOfFileEx與塊的地址塊。因爲地址必須與內存分配粒度相匹配。但映射仍然失敗,錯誤代碼爲ERROR_INVALID_ADDRESS(487)。

接下來我嘗試了與VirtualAloc相同的事情。我的理解是,當我傳遞參數MEM_RESERVE時,我就可以使用那個內存來創建我想要的內容,例如映射文件的視圖。但我發現這是不可能的(與上面相同的錯誤代碼),直到我完全釋放整個塊,再次使用VirtualFree。因此,不再有下一個文件的保留內存。

我已經在使用低碎片堆功能,它對我們來說幾乎沒有用處。重寫我們的代碼只使用較小的文件視圖目前不是一種選擇。我也看了這篇文章Can address space be recycled for multiple calls to MapViewOfFileEx without chance of failure?,但沒有發現它非常有用,並希望有其他的可能性。

你有什麼建議我可以做什麼或者我的設計可能出錯? 謝謝。

+0

到目前爲止,最簡單的解決方案是使用64位尋址。 – MSalters 2012-04-24 10:37:40

+0

@MSalters這肯定會有所幫助,但這意味着比只需要編寫一些新函數以實現正確內存分配的解決方案更多的工作。加上我們的客戶都使用32位。不過謝謝。 – SeeDee 2012-04-24 15:11:48

+0

MMF在Windows中被過度使用。它通過文件系統緩存已經有一個很好的內存映射的文件視圖。我不能告訴你的使用模式,但*做*嘗試只使用ReadFile/SetFilePointer,看看你是否真的有放緩。 – 2012-04-25 00:15:54

回答

0

那麼,MapViewOfFileEx的文檔很清楚:「建議的地址用來指定一個文件應該映射到多個進程中的相同地址,這就要求所有涉及的進程都有地址空間區域。在用於映射的區域中不能發生其他內存分配,包括使用VirtualAlloc

低碎片堆旨在防止即使相對較小的分配失敗。即它避免了1個字節的漏洞,所以2字節的分配可能會更長。你的分配不會小於32位標準。

實際上,這會受到傷害。如果你真的需要它,重新實現內存映射文件。所有必要的功能都可用。使用矢量異常處理程序在源代碼中尋呼,並使用QueryWorkingSet來確定頁面是否髒。

+0

我知道'MapViewOfFileEx'可以用來在進程之間共享內存,但我並不知道它是有意的。重新實現內存映射文件真的會受到傷害,因爲現在我不知道它是如何完成的。我可能不得不考慮這一點。 – SeeDee 2012-04-25 00:47:02