Introduction
Memory mapped files are used for three different purposes:
- To share data between two different processes.
- To access data on a disk file (accessing data on a disk file using memory mapped files shields the user from the details of maintaining a buffer).
- The system uses MMFs to load and execute .exe and .dll files.
This article demonstrates a simple and generic disk file I/O using memory mapped files.
The class CWinMMFIO
is a generic C++ class which can be used wherever file read and write operations are required. The class encapsulates the details of MMF I/O function calls. This class is ideal for reading bigger sized files spanning several giga bytes.
It has been observed that read/write operations are much faster using MMF I/O than using either CFile
or fstream
objects.
Background
Fundamentals of Windows memory management concepts is necessary to understand and modify the code.
Using the code
Following is the public interface to the class:
bool Open(const rstring& strfile, OPENFLAGS oflags);
bool Close();
int Read(void* pBuf, quint nCount);
int Write(void* pBuf, quint nCount);
suint64 Seek(sint64 lOffset, SEEKPOS eseekpos);
suint64 GetPosition();
suint64 GetLength();
bool SetLength(const sint64& nLength);
void GetMMFLastError(rstring& strErr);scription
Interface description
bool Open(const rstring& strfile, OPENFLAGS oflags);
Opens the file strfile
in the access mode defined in the parameter oflags
; the OPENFLAGS
enumerator has two constants, OPN_READ
and OPN_READWRITE
. A zero byte file cannot be opened either for reading or writing.
bool Close();
Unmaps the view of the file, and closes open HANDLE
s to the file mapping object and the opened file.
int Read(void* pBuf, quint nCount);
Reads nCount
number of bytes into the buffer pBuf
; if nCount
number of bytes are not available, then Read
reads as many bytes available from the current position to the end of the file.
The caller must ensure that the buffer pBuf
is at least nCount
number of bytes wide. The function returns the actual number of bytes read. If the current file pointer position is at the end of the file and nCount
is greater than zero, then Read
returns zero.
int Write(void* pBuf, quint nCount);
Writes nCount
number of bytes from pBuf
to the file starting from the current file pointer position. The file size is extended by a quantum of 64KB whenever an attempt is made to write past the end of file. This length is defined by a LONG
internal variable m_lExtendOnWriteLength
. The file will be restored to its actual length when necessary.
suint64 Seek(sint64 lOffset, SEEKPOS eseekpos);
Sets the current file pointer to the location specified by lOffset
relative to SEEKPOS eseekpos
. The SEEKPOS
enumerator has three constants SP_BEGIN
, SP_CUR
, and SP_END
. SP_BEGIN
specifies that the seek is relative to file beginning. SP_CUR
specifies that the seek is relative to the current file pointer. SP_END
specifies that the seek is relative to the end of file.
suint64 GetPosition();
Returns the current file pointer position:
suint64 GetLength();
Returns the actual length of the file in bytes:
bool SetLength(const sint64& nLength);
Sets the length of the file to nLength
bytes. If the length cannot be set, the return value will be false
. Call GetMMFLastError
to get the error message.
void GetMMFLastError(rstring& strErr);
Call GetMMFLastError
to get the error message in the form of a string whenever a function fails.
Points of interest
The Windows SDK function WriteFile
allows the caller to write beyond the EOF by extending the file size as necessary. This facility is not available directly in memory mapped I/O. In order to write and extend the file beyond the current EOF, the view needs to be unmapped and the mapping object must be closed. After this, extend the file size (say by 64K) using the SetEndOfFile
function, recreate the mapping object, and remap the file. The file must be restored to its actual length whenever the write operation completes.
History
- 12 June 09: First version submitted.