記憶體對映檔案（Memorymapped file），或稱 檔案對映、對映檔案，是一段虛擬記憶體逐位元組對應於一個檔案或類檔案的資源，使得應用程式處理對映部分如同訪問主記憶體。 得益 主要用處是增加 IO 效能，特別是用於大檔案。對於小檔案，記憶體對映檔案會導致碎片空間浪費，因為記憶體對映總是要對齊頁邊界，最少耗費 4 KiB。故一個 5 KiB 的檔案將會對映佔用 8 KiB 記憶體，浪費了 3 KiB 記憶體。訪問記憶體對映檔案比直接檔案讀寫要快幾個數量級。 記憶體對映檔案可以只加載一部分內容到使用者的邏輯記憶體空間。這對非常大的檔案特別有用。 使用記憶體對映檔案可以避免：把相當大的檔案直接載入到記憶體時，由於可用記憶體不足，使得一邊讀取檔案記憶體，同時把部分已經載入的檔案從記憶體寫入硬碟虛存檔案中。 記憶體對映檔案由作業系統的記憶體管理程式負責，因此繞過了硬碟虛存的分頁檔案（page file）。 分類 有兩類記憶體對映檔案： Persisted Persisted 檔案與硬碟檔案相關聯，當關閉記憶體對映時，資料被寫入對應的硬碟檔案中。適合於很大的檔案。 Nonpersisted Nonpersisted 檔案並不關聯於硬碟檔案。當關閉記憶體對映檔案，所有資料被拋棄。適用於建立程序間通訊的共享記憶體。 對於 Windows 作業系統，不需要呼叫 CreateFile。呼叫 CreateFileMapping 時，將 INVALID_HANDLE_VALUE 作為 hFile 引數傳入，指示建立的檔案對映物件不是磁碟上的檔案，而是頁交換檔案。所需分配的儲存器大小由 CreateFileMapping 的 dwMaximumSizeHigh 和 dwMaxinumSizeLow 引數決定。 缺點 記憶體對映檔案需要在程序的佔用一塊很大的連續邏輯地址空間。對於 Intel 的 IA32 的 4 GiB 邏輯地址空間，可用的連續地址空間遠遠小於 23 GiB。 相關聯的檔案的 IO 錯誤（如可拔出驅動器或光碟機被彈出，磁碟滿時寫操作等）的記憶體對映檔案會嚮應用程式報告 SIGSEGVSIGBUS 訊號（POSIX 環境）或 EXECUTE_IN_PAGE_ERROR 結構化異常（Windows 環境）。通常的記憶體操作是無需考慮這些異常的。 有記憶體管理單元（MMU）才支援記憶體對映檔案。 用途 最常見用途是絕大多數作業系統 包括 Microsoft Windows 與 Unixlike 系統 用於載入程序。 另一個用途是多個程序的共享記憶體。 第三個用途是對大檔案的讀寫。 支援的平臺 一些可移植的庫實現： BoostInterprocess 在 Boost C Libraries BoostIostreams 也在 Boost C Libraries Fmstream Cppmmf Java 語言的 D 語言的標準庫（stdmmfile module） Ruby 語言的 gem（庫）Mmap Python 語言的 mmap 標準庫模組 Perl 的 SysMmap 或 FileMap Microsoft NET 的 PInvoke，或者 Managed access 參見 MemoryMapped Files 或第三方庫 API PHP 的庫函式 file_get_contents revision log R 語言的一個庫 bigmemory 使用了 Boost 庫的實現 J 語言至少自從 2005 年開始支援記憶體對映檔案。它包括了對盒裝的陣列資料和單一資料型別檔案的支援。支援可以從 datajmf 載入。J 的 Jdb 和 JD 資料庫引擎使用記憶體對映檔案用於列儲存。 類 Unix POSIX 函式 建立一個記憶體對映檔案，需要提供檔案描述符、開始位置的檔案指標、對映長度等引數。 or OpenVMS Windows Windows API 提供了一組函式以實現記憶體對映檔案。 建立或開啟檔案核心物件 HANDLE CreateFile PCSTR pszFileNameDWORD dwDesiredAccessDWORD dwShareModePSECURITY_ATTRIBUTES psaDWORD dwCreationDispositionDWORD dwFlagsAndAttributesHANDLE hTemplateFile 要實現記憶體檔案的修改即時轉換為磁碟檔案的修改，對檔案 CreateFile 時必須寫許可權。Windows 載入 PE 檔案時，會保證寫時複製機制的使用。寫時複製機制指的是同一個可執行檔案的多個程序時，當其中一個程序要改寫其對映檔案的資料時，Windows 會開闢一個新的頁檔案把要修改頁的內容複製到該新頁檔案中並將新的頁檔案與當前程序相關聯。 dwDesiredAccess 的值 0：不能讀取或寫入檔案的內容。用於僅需要獲得檔案的屬性時 GENERIC_READ：可以從檔案中讀取資料 GENERIC_WRITE：可以將資料寫入檔案 GENERIC_READGENERIC_WRITE：可以從檔案中讀取資料，也可以將資料寫入檔案 dwShareMode 的值 0：開啟檔案的任何嘗試均將失敗 FILE_SHARE_READ：使用 GENERIC_WRITE 開啟檔案的其他嘗試將會失敗 FILE_SHARE_WRITE：使用 GENERIC_READ 開啟檔案的其他嘗試將會失敗 FILE_SHARE_READFILE_SHARE_WRITE：開啟檔案的其他嘗試將會取得成功 建立（或開啟）一個檔案對映核心物件 HANDLE CreateFileMapping HANDLE hFilePSECURITY_ATTRIBUTES psaDWORD fdwProtectDWORD dwMaximumSizeHighDWORD dwMaximumSizeLowPCTSTR pszName 第一個引數 hFile 標識想要對映到程序地址空間中的檔案控制代碼。該控制代碼由前面呼叫的 CreateFile 函式返回。 第二個引數 psa 引數指向檔案對映核心物件的 SECURITY_ATTRIBUTES 結構的指標，通常傳遞的值是 NULL（它提供預設的安全特性，返回的控制代碼是不能繼承的）。 第三個引數 fdwProtect 設定保護屬性： PAGE_READONLY：當檔案對映物件被對映時，可以讀取檔案的資料。必須已經將 GENERIC_READ 傳遞給 CreateFile 函式 PAGE_READWRITE：當檔案對映物件被對映時，可以讀取和寫入檔案的資料。必須已經將 GENERIC_READ GENERIC_WRITE 傳遞給 CreateFile PAGE_WRITECOPY：當檔案對映物件被對映時，可以讀取和寫入檔案的資料。如果寫入資料，會導致頁面的私有複製得以建立。必須已經將 GENERIC_READ 或 GENERIC_WRITE 傳遞給 CreateFile SEC_NOCACHE：節保護屬性，告訴系統沒有將檔案的任何記憶體對映頁面放入快取記憶體 SEC_IMAGE：節保護屬性，對映的檔案是個 PE 檔案映像。系統確定 PE 檔案各節的保護屬性賦予檔案映像的各個頁面。例如， PE 檔案的程式碼節（text）通常用 PAGE_EXECUTE_READ 屬性， 而 PE 檔案的資料節 data 通常用 PAGE_READWRITE 屬性。 SEC_RESERVE：節保護屬性 SEC_COMMIT：節保護屬性 第四和五個引數 dwMaximumSizeHigh 和 dwMaximumSizeLow：該檔案的最大位元組數 第六個引數 pszName：以 0 結尾的字串，給該檔案對映物件賦予一個名字。該名字用於與其他程序共享檔案對映物件。 檔案資料對映到程序地址空間並提交 PVOID MapViewOfFile HANDLE hFileMappingObjectDWORD dwDesiredAccessDWORD dwFileOffsetHighDWORD dwFileOffsetLowSIZE_T dwNumberOfBytesToMap 第一個引數 hFileMappingObject 標識檔案對映物件的控制代碼，該控制代碼是前面呼叫 CreateFileMapping 或 OpenFileMapping 函式返回的。 第二個引數 dwDesiredAccess 標識如何訪問該資料 FILE_MAP_WRITE：可以讀取和寫入檔案資料。CreateFileMapping 函式必須透過傳遞 PAGE_READWRITE 標誌來呼叫 FILE_MAP_READ：可以讀取檔案資料。CreateFileMapping 函式可以透過傳遞下列任何一個保護屬性來呼叫：PAGE_READONLY、PAGE_ READWRITE 或 PAGE_WRITECOPY FILE_MAP_ALL_ACCESS：與 FILE_MAP_WRITE 相同 FILE_MAP_COPY：可以讀取和寫入檔案資料。如果寫入檔案資料，可以建立一個頁面的私有複製。CreateFileMapping 函式可以用 PAGE_READONLY、PAGE_READWRITE 或 PAGE_WRITECOPY 等保護屬性中的任何一個來呼叫。 第三、四個引數 dwFileOfsetHigh 和 dwFileOfsetLow：指定從哪個位元組開始作為檢視中的第一個位元組來對映。 第五個引數 dwNumberOfBytesToMap 指出多少位元組要對映到地址空間。如果設定的值是 0，那麼系統將設法把從檔案中的指定位移開始到整個檔案的結尾的檢視對映到地址空間。 從程序地址空間撤消檔案對映 BOOL UnmapViewOfFile PVOID pvBaseAddress 引數 pvBaseAddress 由 MapViewOfFile 函式返回。 強制系統將修改過的資料重新寫入磁碟 BOOL FlushViewOfFile PVOID pvAddressSIZE_T dwNumberOfBytesToFlush 第一個引數是記憶體對映檔案檢視的一個位元組的地址。 第二個引數指明要重新整理的位元組數。 關閉檔案對映物件：用 CloseHandle 函式 檔案物件：用 CloseHandle 函式 參見 儲存器對映輸入輸出 參考文獻 Category 虛擬記憶體