打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
Windows系统程序设计之内存映射

标 题:Windows系统程序设计之内存映射
作 者: 北极星2003
时 间: 2006-08-11 22:03
链 接: http://bbs.pediy.com/showthread.php?threadid=30410
详细信息:

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

【作者】北极星2003
【来源】看雪技术论坛(bbs.pediy.com) 
【时间】2006年8月11日

  相信对于大家来说,内存映射技术已经是个很熟悉的技术了。在这里我只是作个总结,希望对那些新手朋友有帮助。

  内存映射文件通常有两个用途:一是内存映射磁盘文件,这对于大数据文件的处理比较适合;二是共享内存,作为进程间通信的一种方式。

附件:memmap.rar

实例一:内存映射实例--文件分割器

 


 
1、  设计目标
设计文件分割器,作为演示内存映射磁盘文件实例。

2、  设计思路
  内存映射磁盘文件的一般步骤:
(1)  打开文件
(2)  创建内存映射内核对象
(3)  映射文件视图
(4)  在内存中处理数据
(5)  卸载文件视图
(6)  关闭内存映射内核对象
(7)  关闭文件

分割思路,把原文件按照设置的文件块大小依次映射到内存,然后生成一个新文件,下图中蓝色箭头所示。
还原思路,把子文件依次映射到内存,然后再回写到原文件的各个部分,下图中红色箭头所示。
 
 
3、  详细设计
(1)  定义文件信息块结构
文件信息块保存着分割文件时的信息,也是还原时的必备文件。

代码:
typedef struct _FILE_ITEM_INFO {  DWORD  dwLowFileSize ;    // 文件大小低字段  DWORD  dwHighFileSize ;  // 文件大小高字段  DWORD  dwPartSize ;      // 文件块大小  DWORD  dwPartNum ;    // 文件块数量  CString  szFileName ;      // 源文件名} FILE_ITEM_INFO ;typedef FILE_ITEM_INFO* PFILE_ITEM_INFO ;



(2)  文件分割实现部分

代码:
DWORD CFD::FDFileDivide  ( PFILE_ITEM_INFO pItem ){  // 删除该文件原有的分块文件  this->DeleteAllPartFiles ( pItem->szFileName ) ;  // 创建信息文件  HANDLE hFile = CreateFile (     pItem->szFileName + ".INFO",      GENERIC_READ|GENERIC_WRITE,     FILE_SHARE_READ|FILE_SHARE_WRITE,     NULL,     CREATE_ALWAYS,     FILE_ATTRIBUTE_NORMAL,     NULL ) ;  if ( hFile == INVALID_HANDLE_VALUE )    return GetLastError() ;    // 写入信息文件  DWORD dwWriteByte ;  WriteFile ( hFile, &(pItem->dwLowFileSize),  sizeof(DWORD),  &dwWriteByte, NULL ) ;  WriteFile ( hFile, &(pItem->dwPartSize),  sizeof(DWORD),  &dwWriteByte, NULL ) ;  WriteFile ( hFile, &(pItem->dwPartNum),    sizeof(DWORD),  &dwWriteByte, NULL ) ;  CloseHandle ( hFile ) ;  // 打开目标文件  hFile = CreateFile (     pItem->szFileName,      GENERIC_READ,     FILE_SHARE_READ|FILE_SHARE_WRITE,     NULL,     OPEN_EXISTING,     FILE_ATTRIBUTE_NORMAL,     NULL ) ;  if ( hFile == INVALID_HANDLE_VALUE )    return GetLastError() ;  // 创建文件内存映射内核对象  HANDLE hMapFile = CreateFileMapping (     hFile,       NULL,     PAGE_READONLY,     0,     0,     NULL ) ;  if ( hMapFile == NULL )  {    CloseHandle ( hFile ) ;    return GetLastError() ;  }  CString TempStr ;  DWORD  dwCurAddr = 0, dwCurPart = 0 ;  LPVOID lpMapAddr = 0 ;  // 分块循环映射文件  for ( UINT i = 1; i <= pItem->dwPartNum; i++ )  {    dwCurPart = pItem->dwLowFileSize - dwCurAddr ;    if ( dwCurPart > pItem->dwPartSize )      dwCurPart = pItem->dwPartSize ;    lpMapAddr = MapViewOfFile ( hMapFile, FILE_MAP_READ, 0, dwCurAddr, dwCurPart ) ;    if ( lpMapAddr == NULL )    {      CloseHandle ( hMapFile ) ;      CloseHandle ( hFile ) ;      return GetLastError() ;    }    dwCurAddr += dwCurPart ;    TempStr.Format ( "%s.PART_%d", pItem->szFileName, i ) ;    DeleteFile ( TempStr ) ;        HANDLE hNewFile = CreateFile (       TempStr,      GENERIC_READ|GENERIC_WRITE,       FILE_SHARE_READ|FILE_SHARE_WRITE,       NULL,       CREATE_ALWAYS,       FILE_ATTRIBUTE_NORMAL,       NULL ) ;    if ( hFile == INVALID_HANDLE_VALUE )      return GetLastError() ;        HANDLE hNewMapFile = CreateFileMapping (      hNewFile,         NULL,       PAGE_READWRITE,       0,       dwCurPart,       NULL ) ;    if ( hNewMapFile == NULL )    {      CloseHandle ( hNewFile ) ;      return GetLastError() ;    }    LPVOID lpNewMapAddr = MapViewOfFile ( hNewMapFile, FILE_MAP_WRITE, 0, 0, 0 ) ;    if ( lpMapAddr == NULL )    {      CloseHandle ( hNewMapFile ) ;      CloseHandle ( hNewFile ) ;      return GetLastError() ;    }    memcpy ( lpNewMapAddr, lpMapAddr, dwCurPart ) ;        UnmapViewOfFile ( lpMapAddr ) ;    UnmapViewOfFile ( lpNewMapAddr ) ;    CloseHandle ( hNewMapFile ) ;    CloseHandle ( hNewFile ) ;  }  CloseHandle ( hMapFile ) ;  CloseHandle ( hFile ) ;  return 0 ;}




(3)  文件还原部分

代码:
DWORD CFD::FDFileConnect  ( PFILE_ITEM_INFO pItem ){  DeleteFile ( pItem->szFileName ) ;  // 打开目标文件  HANDLE hFile = CreateFile (     pItem->szFileName,      GENERIC_READ|GENERIC_WRITE,     FILE_SHARE_READ|FILE_SHARE_WRITE,     NULL,     CREATE_ALWAYS,     FILE_ATTRIBUTE_NORMAL,     NULL ) ;  if ( hFile == INVALID_HANDLE_VALUE )    return GetLastError() ;  // 创建文件内存映射内核对象  HANDLE hMapFile = CreateFileMapping (     hFile,       NULL,     PAGE_READWRITE,     0,     pItem->dwLowFileSize,     NULL ) ;  if ( hMapFile == NULL )  {    CloseHandle ( hFile ) ;    return GetLastError() ;  }  CString TempStr ;  DWORD  dwCurAddr = 0, dwCurPart = 0 ;  LPVOID lpMapAddr = 0 ;  // 分块循环映射文件  for ( UINT i = 1; i <= pItem->dwPartNum; i++ )  {    dwCurPart = pItem->dwLowFileSize - dwCurAddr ;    if ( dwCurPart > pItem->dwPartSize )      dwCurPart = pItem->dwPartSize ;    lpMapAddr = MapViewOfFile ( hMapFile, FILE_MAP_WRITE, 0, dwCurAddr, dwCurPart ) ;    if ( lpMapAddr == NULL )    {      CloseHandle ( hMapFile ) ;      CloseHandle ( hFile ) ;      return GetLastError() ;    }    dwCurAddr += dwCurPart ;    TempStr.Format ( "%s.PART_%d", pItem->szFileName, i ) ;        HANDLE hNewFile = CreateFile (       TempStr,      GENERIC_READ,       FILE_SHARE_READ|FILE_SHARE_WRITE,       NULL,       OPEN_EXISTING,       FILE_ATTRIBUTE_NORMAL,       NULL ) ;    if ( hFile == INVALID_HANDLE_VALUE )    {      UnmapViewOfFile ( lpMapAddr ) ;      CloseHandle ( hMapFile ) ;      CloseHandle ( hFile ) ;      return GetLastError() ;    }        HANDLE hNewMapFile = CreateFileMapping (      hNewFile,         NULL,       PAGE_READONLY,       0,       0,       NULL ) ;    if ( hNewMapFile == NULL )    {        UnmapViewOfFile ( lpMapAddr ) ;      CloseHandle ( hMapFile ) ;      CloseHandle ( hFile ) ;      CloseHandle ( hNewFile ) ;      return GetLastError() ;    }    LPVOID lpNewMapAddr = MapViewOfFile ( hNewMapFile, FILE_MAP_READ, 0, 0, 0 ) ;    if ( lpMapAddr == NULL )    {        UnmapViewOfFile ( lpMapAddr ) ;      CloseHandle ( hMapFile ) ;      CloseHandle ( hFile ) ;      CloseHandle ( hNewMapFile ) ;      CloseHandle ( hNewFile ) ;      return GetLastError() ;    }    memcpy ( lpMapAddr, lpNewMapAddr, dwCurPart ) ;    FlushViewOfFile ( lpMapAddr, dwCurPart ) ;    UnmapViewOfFile ( lpMapAddr ) ;    UnmapViewOfFile ( lpNewMapAddr ) ;    CloseHandle ( hNewMapFile ) ;    CloseHandle ( hNewFile ) ;  }  CloseHandle ( hMapFile ) ;  CloseHandle ( hFile ) ;  this->DeleteAllPartFiles ( pItem->szFileName ) ;  return 0 ;}




(4)  性能测试
对于小文件没有测试的必要,这里选个较大的文件作为测试对象。
测试平台信息:P4 2.26GHz + WinXP sp2 + 256 MB内存
测试对象大小:203 MB
如果块大小为 10 MB, 分割需6秒左右,还原(合并)需7秒左右
如果块大小为 1 MB, 分割需13秒左右,还原(合并)需12秒左右

 
实例二:共享内存示例
 

 

 

1、  设计目标
在两个相互独立的进程间通过文件映射对象来分配和访问同一个共享内存块的应用实例。

2、  设计思路
这个例子比较简单,从写入端进程把信息写到共享内存,然后读取端进程从共享内存中读取信息。
 
 
3、  详细设计
(1)  创建共享内存

代码:
void CShareMemDlg::OnSetup() {  if ( bSetup )  {    this->MessageBox ( "已经建立共享内存文件" ) ;    return ;  }  hMapFile = CreateFileMapping (    INVALID_HANDLE_VALUE,    NULL,    PAGE_READWRITE | SEC_COMMIT,    0,    uShareMemSize,    "ShareMemSample" ) ;  if ( hMapFile == NULL )  {    this->MessageBox ( "创建共享内存映射文件失败!" ) ;    return ;  }  lpBase  = MapViewOfFile (     hMapFile,     FILE_MAP_READ|FILE_MAP_WRITE,    0,    0,    0 ) ;  if ( this->lpBase == NULL )  {    this->MessageBox ( "创建共享内存映射文件失败!" ) ;    return ;  }  this->MessageBox ( "创建内存共享成功!" ) ;  bSetup = true ;}



  (2)从共享内存中读取信息

代码:
void CShareMemReadDlg::OnRead() {  HANDLE hMapFile = OpenFileMapping ( FILE_MAP_READ, FALSE, "ShareMemSample");   if ( hMapFile == NULL )  {    DWORD dwErrorCode = GetLastError () ;    this->MessageBox ( "打开共享内存映射文件失败!" ) ;    return ;  }  LPVOID lpBase = MapViewOfFile (     hMapFile,     FILE_MAP_READ,    0,    0,    0 ) ;  if ( lpBase == NULL )  {    DWORD dwErrorCode = GetLastError () ;    this->MessageBox ( "打开共享内存映射文件失败!" ) ;    return ;  }  char *pReadInfo = (char*)lpBase ;  UINT uLength = strlen ( pReadInfo ) ;      memcpy ( this->m_ReadInfo.GetBuffer( uLength + 1 ), lpBase, uLength + 1 ) ;  this->UpdateData ( false ) ;  UnmapViewOfFile ( lpBase ) ;  CloseHandle ( hMapFile ) ;}




【参考文献】
[1].Windows核心编程 Jeffrey Richter著

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
c++内存映射文件
VC++ 中使用内存映射文件处理大文件
关于内存映射文件技术处理大文件的读写
c++/MFC 封装好的文件内存映射类(转)
C++使用共享内存实现进程间通信
压缩解压缩的函数库zlib的使用--gqlyxg1981的博客
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服