C++中內存映射文件怎么用?mmap跨平臺實現

內存映射文件是將磁盤文件映射到進程地址空間,使程序像訪問內存一樣操作文件內容。1. 它通過操作系統自動管理緩存和分頁,提高大文件處理效率;2. linux 使用 mmap 和 munmap 實現,需指定映射地址、大小、權限、標志等參數;3. windows 通過 createfilemapping 和 mapviewoffile 實現類似功能;4. 跨平臺封裝可通過類實現不同系統調用各自 api,統一接口為 map 和 unmap;5. 使用時需注意文件大小、讀寫模式、錯誤判斷及資源釋放。

C++中內存映射文件怎么用?mmap跨平臺實現

c++中使用內存映射文件(Memory-Mapped File)是一種高效的文件讀寫方式,尤其適合處理大文件。它通過將文件映射到進程的地址空間,使得程序可以直接像訪問內存一樣訪問文件內容。mmap 是 linux 系統下常用的內存映射函數,但在 windows 上沒有直接對應的 mmap,需要做跨平臺適配。

C++中內存映射文件怎么用?mmap跨平臺實現


什么是內存映射文件?

內存映射文件的核心思想是:把磁盤上的文件映射成一段內存地址。這樣讀寫文件就像操作數組一樣方便,而且操作系統會自動管理緩存和分頁,效率很高。

C++中內存映射文件怎么用?mmap跨平臺實現

比如你想讀取一個幾十GB的日志文件,用傳統 fread 或 ifstream 可能會很慢,但用內存映射就可以按需加載部分數據,節省時間和資源。

立即學習C++免費學習筆記(深入)”;


mmap 的基本用法(Linux)

在 Linux 下,使用的是 中的 mmap 函數:

C++中內存映射文件怎么用?mmap跨平臺實現

void* mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
  • addr:建議的映射起始地址,通常設為 nullptr
  • length:映射區域大小
  • prot:訪問權限,如 PROT_READ、PROT_WRITE
  • flags:映射選項,如 MAP_SHAred(修改會寫回文件)、MAP_PRIVATE(私有副本)
  • fd:打開的文件描述符
  • offset:文件偏移量(必須是頁對齊的)

示例代碼片段:

int fd = open("example.txt", O_RDONLY); char* data = (char*) mmap(nullptr, file_size, PROT_READ, MAP_SHARED, fd, 0); // 使用 data 操作文件內容 munmap(data, file_size); close(fd);

Windows 下怎么實現類似功能?

Windows 并不支持 mmap,但提供了類似的機制:CreateFileMapping + MapViewOfFile

步驟如下:

  • 打開文件:CreateFile
  • 創建文件映射對象:CreateFileMapping
  • 映射到內存:MapViewOfFile
  • 最后記得清理:UnmapViewOfFile 和 CloseHandle

示例偽代碼結構:

HANDLE hFile = CreateFile(...); HANDLE hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL); char* data = (char*) MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0); // 使用 data UnmapViewOfFile(data); CloseHandle(hMap); CloseHandle(hFile);

如何實現跨平臺的 mmap 封裝?

為了統一接口,可以做一個簡單的封裝,在不同系統下調用各自 API:

class MemoryMappedFile { public:     void* map(const char* filename, size_t& out_size);     void unmap(); private: #ifdef _WIN32     HANDLE hMap; #else     int fd; #endif     void* data; };

在 .cpp 文件中根據平臺分別實現:

  • Windows 版本調用 CreateFileMapping 等
  • Linux/macos 調用 open, mmap, munmap

封裝后用戶只需要知道 map() 和 unmap() 即可,不用關心底層細節。


實際使用中的注意事項

  • 文件大小要提前知道,否則無法確定映射長度
  • 注意只讀/讀寫模式的選擇
  • 映射失敗時要判斷返回值是否為 MAP_FaiLED 或 nullptr
  • 如果是只讀場景,盡量使用 MAP_PRIVATE 或 PROT_READ 來提高安全性
  • 不要忘記釋放資源(munmap / UnmapViewOfFile)

基本上就這些。雖然不同系統 API 不同,但邏輯差不多,只要做好封裝,就能寫出跨平臺兼容的內存映射文件操作代碼。

? 版權聲明
THE END
喜歡就支持一下吧
點贊10 分享