内存映射文件点滴

文件操作,不可或缺。

但在海量数据存储与Limited Resource系统来说,常常会用到内存映射。通过文件映射,磁盘文件的全部或部分内容与进程虚拟地址空间的某个区域建立映射关联,可以直接对被映射的文件进行访问,而不必执行Read/Write之类的文件I/O操作,无需对文件内容进行缓冲处理。在MongoDB中,当服务启动是,数据文件就会映射到内存中,具体可看看Dai的<MongoDB 源码分析>,或直接把MongoDB下了来看看。

内存映射文件点滴

此外,内存映射还可以用于进程间数据共享,对于大数据量同步尤其如此,N多程序库中所谓的SharedMemory的内部实现就是MemoryMappedFile。

内存映射文件点滴

下面就是内存映射文件的一些代码:

MemoryMappedFile:

class MemoryMappedFileImpl : public BedRock::UnCopyable
{
public:
bool attach(const BedRock::WideString& filePath);
void detach();
private:
HANDLE m_fileHandle;
HANDLE m_fileMappedHandle;
BedRock::UInt8
* m_fileBuffer;
size_t m_length;
};

Map File to Memory:

bool MemoryMappedFileImpl::attach(const BedRock::WideString& filePath)
{
m_fileHandle
= CreateFile(filePath.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
SMCP_ASSERT(m_fileHandle);
if(m_fileHandle == INVALID_HANDLE_VALUE) return false;

BY_HANDLE_FILE_INFORMATION fileInformation;
BOOL bStatus
= GetFileInformationByHandle( m_fileHandle, &fileInformation);
m_length
= (size_t) fileInformation.nFileSizeLow; // 32bit only for now.

m_fileMappedHandle
= ::CreateFileMapping(m_fileHandle, NULL, PAGE_READONLY, 0, m_length, NULL);
if(m_fileMappedHandle)
{
m_fileBuffer
= static_cast<BedRock::UInt8*>(MapViewOfFile( m_fileMappedHandle, FILE_MAP_READ, 0, 0, m_length));
}

return m_fileBuffer != NULL;
}

Unmap:

void MemoryMappedFileImpl::detach()
{
m_filePath.empty();
m_length
= INVALID_FILE_SIZE;

if (m_fileBuffer)
{
::UnmapViewOfFile(m_fileBuffer);
m_fileBuffer
= NULL;
}

if( m_fileMappedHandle != INVALID_HANDLE_VALUE )
{
::CloseHandle( m_fileMappedHandle );
m_fileMappedHandle
= INVALID_HANDLE_VALUE;
}

if( m_fileHandle != INVALID_HANDLE_VALUE )
{
::CloseHandle( m_fileHandle );
m_fileHandle
= INVALID_HANDLE_VALUE;
}
}

-

More Materials:

Windows核心编程

看雪之Windows系统程序设计之内存映射


你可能感兴趣的:(文件)