File Mapping APIs
File mapping allows you to treat the contents of a file as if they were memory. This can significantly improve performance for I/O-intensive applications by reducing the overhead of traditional read/write operations. Instead of copying data between user-space buffers and kernel-space buffers, you can directly access file contents in memory.
Introduction to File Mapping
File mapping provides a powerful mechanism for inter-process communication (IPC) and for efficiently accessing large files. It involves mapping a portion of a file (or the entire file) into the virtual address space of a process. Once mapped, the file's data can be accessed using standard memory pointers.
Key Concepts
- Page File Mapping: Mapping a file directly into memory without an underlying file on disk. Used for shared memory regions.
- Section Objects: The underlying kernel objects that represent a file mapping.
- Views: A specific portion of a section object mapped into a process's address space.
Core APIs
The following functions are central to using file mapping in Windows:
CreateFileMapping
This function creates or opens a named or unnamed file mapping object for a specified file.
HANDLE CreateFileMapping(
HANDLE hFile,
LPSECURITY_ATTRIBUTES lpAttributes,
DWORD flProtect,
DWORD dwMaximumSizeHigh,
DWORD dwMaximumSizeLow,
LPCTSTR lpName
);
hFile: A handle to the file to be mapped.lpAttributes: Security attributes.flProtect: Memory protection for the mapping object (e.g.,PAGE_READWRITE,PAGE_EXECUTE_READ).dwMaximumSizeHigh,dwMaximumSizeLow: The maximum size of the mapping object.lpName: The name of the mapping object (if named).
MapViewOfFile
This function maps a view of a file mapping object into the address space of the calling process.
LPVOID MapViewOfFile(
HANDLE hFileMappingObject,
DWORD dwDesiredAccess,
DWORD dwFileOffsetHigh,
DWORD dwFileOffsetLow,
SIZE_T dwNumberOfBytesToMap
);
hFileMappingObject: The handle to the file mapping object.dwDesiredAccess: The desired access to the mapped view (e.g.,FILE_MAP_READ,FILE_MAP_WRITE).dwFileOffsetHigh,dwFileOffsetLow: The offset within the file mapping object from which to start the view.dwNumberOfBytesToMap: The number of bytes of the mapping object to map.
UnmapViewOfFile
This function unmaps a mapped view of a file from the calling process's address space.
BOOL UnmapViewOfFile(
LPCVOID lpBaseAddress
);
lpBaseAddress: The base address of the mapped view to be unmapped.
CloseHandle
Remember to close handles to file mapping objects and files when they are no longer needed using CloseHandle.
Use Cases
- Efficient Large File Access: Read and write to large files without loading the entire file into RAM.
- Inter-Process Communication (IPC): Create shared memory regions between multiple processes for fast data exchange.
- Executable Code Loading: Load executable code directly from files into memory.
Important Note:
When using file mapping for IPC, ensure proper synchronization mechanisms (like mutexes or semaphores) are in place to prevent race conditions.
Performance Tip:
Map files with FILE_MAP_ALL_ACCESS for maximum flexibility, but be mindful of security implications. Use more restrictive access flags (e.g., FILE_MAP_READ) when possible.
Example: Reading from a Mapped File
This is a simplified conceptual example:
HANDLE hFile = CreateFile(L"mydata.bin", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) { /* Error handling */ }
HANDLE hMapFile = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
if (hMapFile == NULL) { CloseHandle(hFile); /* Error handling */ }
LPVOID pBuf = MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0);
if (pBuf == NULL) { CloseHandle(hMapFile); CloseHandle(hFile); /* Error handling */ }
// Now you can read from pBuf as if it were an array
const char* data = (const char*)pBuf;
size_t fileSize = GetFileSize(hFile, NULL);
printf("Data from file: %.*s\n", (int)fileSize, data);
UnmapViewOfFile(pBuf);
CloseHandle(hMapFile);
CloseHandle(hFile);