File Mapping in C++ Applications
File mapping is a concept where a file map object can be created for a file on the disk. Thereafter, different processes can create a view of this file mapping object in their virtual address spaces. A process can create one or more views of the file mapping object in its virtual address space and work on it. Below is the working diagram for the file mapping object:
Do remember the following key points
- The file is present on the disk of the machine on which the processes are running.
- The file mapping object is present in the physical memory.
- More than one process can create views for the same file mapping object.
- The file mapping object can contain the entire file or a part of it. Similarly, the file view for processes can contain the entire file mapping object or a part of it.
- All the copies are coherent and the same as that present on the disk.
- It is a great help when working with huge files like database files as not the whole file needs to be present in the physical memory.
- More than one process can use a file on the disk for both read and write operations. Each process can create a new view, un-mapping the current file view.
Steps to create a file mapping object and file view
Step 1: Create or open a file object that represents the file on the disk. Here, we created a new file object with handle as hFile and named as “datafile.txt”.
HANDLE CreateFileA( LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile ); // Can be used as HANDLE hFile = CreateFile(TEXT("datafile.txt"), GENERIC_READ | GENERIC_WRITE, 0, // Open with exclusive access NULL, // No security attributes // Creating a new temp file CREATE_NEW, // Delete the file after unmapping the view FILE_FLAG_DELETE_ON_CLOSE, NULL);
HANDLE CreateFileA( LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile ); // Can be used as HANDLE hFile = CreateFile(TEXT("datafile.txt"), GENERIC_READ | GENERIC_WRITE, 0, // open with exclusive access NULL, // no security attributes CREATE_NEW, // creating a new temp file FILE_FLAG_DELETE_ON_CLOSE, //delete the file after unmapping the view NULL);
Step 2: Create a map object for the file that contains information about how to access the file and its size. So, after creating the above file we use its handle and create its mapping in the physical memory.
HANDLE CreateFileMappingA( HANDLE hFile, LPSECURITY_ATTRIBUTES lpFileMappingAttributes, DWORD flProtect, DWORD dwMaximumSizeHigh, DWORD dwMaximumSizeLow, LPCSTR lpName ); // Can be used as HANDLE hFileMapping = ::CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, bufferSize, filename);
Step 3: Map all or part of the file-mapping object from the physical memory into your process’s virtual address space. So here we are creating the view of the mapped file which will be used by the process.
LPVOID MapViewOfFile( HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh, DWORD dwFileOffsetLow, SIZE_T dwNumberOfBytesToMap ); // Can be used as void* p = ::MapViewOfFile(hFileMapping, FILE_MAP_ALL_ACCESS, 0, param1, param2);
Step 4: Cleaning up
4(A) Un-map the file mapping object from the process address space. Backtrack the above steps and firstly, remove the file views from the process’s address space.
BOOL UnmapViewOfFile(LPCVOID lpBaseAddress ); // Can be used as UnmapViewOfFile(p);
4(B) Close the file mapping object. This step removes the file mapping from physical memory.
4(C) Close the file object. Here, close the file opened on the disk and free the handle. Since in the first step we set flag FILE_FLAG_DELETE_ON_CLOSE, the file will be deleted after this step.
- Close the handles in the same order or else it will give rise to discrepancies.
- Close all the open file handles before trying to delete the file.