当前位置: 首页 > backend >正文

MFC内存映射文件

MFC内存映射文件是由一个文件到一块内存的映射。Win32提供了允许应用程序把文件映射到一个进程的函数 (CreateFileMapping)。内存映射文件与虚拟内存有些类似,通过内存映射文件可以保留一个地址空间的区域,同时将物理存储器提交给此区域,内存文件映射的物理存储器来自一个已经存在于磁盘上的文件,而且在对该文件进行操作之前必须首先对文件进行映射。使用内存映射文件处理存储于磁盘上的文件时,将不必再对文件执行I/O操作,使得内存映射文件在处理大数据量的文件时能起到相当重要的作用。

内存映射文件一般有以下三个作用

  1. 读取文件
  2. Windows系统加载和执行程序的exe文件和DLL文件。
  3. 在多个进程之间通过内存映射文件交换数

读文的几种方式:

一般读文件有以下几种方式:

  1. C语言:通过File* PFile = fopen(“文件名”)
  2. C++:输出文件流:ofstream ofs(“文件名”)

                    输入文件流:ifs(“文件名”)

  1. Windows API函数:HANDLE hFife = CreateFile(...)

                                         WriteFile(...)

       以上三种函数都可以回去文件的类容,但是不是最好的方法,而使用内存映射文件是最好的,但是用此技术读取文件有些大材小用了。

 

内存映射文件的步骤:

  • 第一步、创建文件对象 CreateFile()
  • 第二步、创建文件映射对象CreateFileMapping()
  • 第三步、将文件的数据映射到进程的地址空间 MapViewofFile()
  • 第四步、从进程的地址空间撤销对文件数据的映射  UNmapViewofFile()
  • 第五步、关闭文件映射对象  CloseHandle()
  • 第六步、关闭文件对象 CloseHandle()

使用的函数

1、CreateFile()

        这是一个多功能的函数,可打开或创建文件或者I/O设备,并返回可访问的句柄:控制台,通信资源,目录(只读打开),磁盘驱动器,文件,邮槽,管道。

HANDLE CreateFile(LPCTSTR lpFileName, //普通文件名或者设备文件名DWORD dwDesiredAccess, //访问模式(写/读)DWORD dwShareMode, //共享模式LPSECURITY_ATTRIBUTES lpSecurityAttributes, //指向安全属性的指针DWORD dwCreationDisposition, //如何创建DWORD dwFlagsAndAttributes, //文件属性HANDLE hTemplateFile //用于复制文件句柄);
  • lpFileName String要打开的文件的名或设备名。这个字符串的最大长度在ANSI版本中为MAX_PATH,在unicode版本中为32767。
  • dwDesiredAccess指定类型的访问对象。如果为 GENERIC_READ 表示允许对设备进行读访问;如果为 GENERIC_WRITE 表示允许对设备进行写访问(可组合使用);如果为零,表示只允许获取与一个设备有关的信息 。另外,还可以指定下面的控制标志:

标准控制权限(16-23位掩码):

DELETE删除对象的权限。
READ_CONTROL从对象的安全描述符中读取信息的权限,但不包括SACL(系统访问控制列表)中的信息。
WRITE_DAC 修改对象安全描述符中的DACL(随机访问控制列表)的权限
WRITE_OWNER修改对象安全描述符中的属主的权限
SYNCHRONIZE同步化使用对象的权限,即可以创建一个线程等待信号量释放(但有些对象不支持这个权限)。
STANDARD_RIGHTS_REQUIRED 等价于前面四种权限的总合(通常这四种是必须具有的权限)。
STANDARD_RIGHTS_READ一般等价于READ_CONTROL
STANDARD_RIGHTS_WRITE一般等价于WRITE_CONTROL
STANDARD_RIGHTS_EXECUTE一般等价于EXECUTE_CONTROL
STANDARD_RIGHTS_ALL等价于前面五种权限的总合。

 

          特殊控制权限(0-15位掩码):

           

SPECIFIC_RIGHTS_ALL 
ACCESS_SYSTEM_SECURITY 
MAXIMUM_ALLOWED 
GENERIC_READ 
GENERIC_WRITE 
GENERIC_EXECUTE 
GENERIC_ALL 

           注:实质上是通过ACCESS_MASK结构体的一个双字值来设置标准权限、特殊权限和一般权限的。

  • dwShareModeLong, 如果是零表示不共享; 如果是FILE_SHARE_DELETE表示随后打开操作对象会成功,但只有删除访问请求的权限;如果是FILE_SHARE_READ随后打开操作对象会成功只有请求读访问的权限;如果是FILE_SHARE_WRITE 随后打开操作对象会成功,但只有请求写访问的权限。
  • lpSecurityAttributesSECURITY_ATTRIBUTES, 指向一个SECURITY_ATTRIBUTES结构的指针,定义了文件的安全特性(如果操作系统支持的话)
  • dwCreationDispositionLong,下述常数之一:
CREATE_NEW 创建文件;如文件存在则会出错
CREATE_ALWAYS创建文件,会改写前一个文件
OPEN_EXISTING 文件必须已经存在。由设备提出要求
OPEN_ALWAYS 如文件不存在则创建它
TRUNCATE_EXISTING 将现有文件缩短为零长度
  • dwFlagsAndAttributesLong, 一个或多个下述常数
FILE_ATTRIBUTE_ARCHIVE 标记归档属性
FILE_ATTRIBUTE_COMPRESSED 将文件标记为已压缩,或者标记为文件在目录中的默认压缩方式
FILE_ATTRIBUTE_NORMAL 默认属性
FILE_ATTRIBUTE_HIDDEN隐藏文件或目录
FILE_ATTRIBUTE_READONLY 文件为只读
FILE_ATTRIBUTE_SYSTEM 文件为系统文件
FILE_FLAG_WRITE_THROUGH 操作系统不得推迟对文件的写操作
FILE_FLAG_OVERLAPPED允许对文件进行重叠操作
FILE_FLAG_NO_BUFFERING禁止对文件进行缓冲处理。文件只能写入磁盘卷的扇区块
FILE_FLAG_RANDOM_ACCESS针对随机访问对文件缓冲进行优化
FILE_FLAG_SEQUENTIAL_SCAN 针对连续访问对文件缓冲进行优化
FILE_FLAG_DELETE_ON_CLOSE关闭了上一次打开的句柄后,将文件删除。特别适合l临时文件

 

           也可在Windows NT下组合使用下述常数标记:

SECURITY_ANONYMOUS, SECURITY_IDENTIFICATION, SECURITY_IMPERSONATION, SECURITY_DELEGATION, SECURITY_CONTEXT_TRACKING, SECURITY_EFFECTIVE_ONLY

  • hTemplateFile,hTemplateFile为一个文件或设备句柄,表示按这个参数给出的句柄为模板创建文件(就是将该句柄文件拷贝到lpFileName指定的路径,然后再打开)。它将指定该文件的属性扩展到新创建的文件上面,这个参数可用于将某个新文件的属性设置成与现有文件一样,并且这样会忽略dwAttrsAndFlags。通常这个参数设置为NULL,为空表示不使用模板,一般为空。
  • 返回值Long,如执行成功,则返回文件句柄。INVALID_HANDLE_VALUE表示出错

 

2、CreateFileMapping()

CreateFileMapping函数用于创建一个文件映射内核对象

HANDLE CreateFileMapping(HANDLE hFile, //物理文件句柄LPSECURITY_ATTRIBUTES lpAttributes, //安全设置DWORD flProtect, //保护设置DWORD dwMaximumSizeHigh, //高位文件大小DWORD dwMaximumSizeLow, //低位文件大小LPCTSTR lpName //共享内存名称
);
  • hFile:Long,指定欲在其中创建映射的一个文件句柄。0xFFFFFFFF(-1,即INVALID_HANDLE_VALUE)表示在页面文件中创建一个可共享的文件映射。
  • lpFileMappigAttributes:SECURITY_ATTRIBUTES,它指明返回的句柄是否可以被子进程所继承,指定一个安全对象,在创建文件映射时使用。如果为NULL(用ByVal As Long传递零),表示使用默认安全对象。

    flProtect:Long,下述常数之一:

PAGE_READONLY

以只读方式打开映射

PAGE_READWRITE 以可读、可写方式打开映射
PAGE_WRITECOPY为写操作留下备份

 

 

      可组合使用下述一个或多个常数:

SEC_COMMIT 为文件映射一个小节中的所有页分配内存
SEC_IMAGE文件是个可执行文件
SEC_RESERVE为没有分配实际内存的一个小节保留虚拟内存空间

 

  • dwMaximumSizeHigh:Long,文件映射的最大长度的高32位。
  • dwMaximumSizeLow:Long,文件映射的最大长度的低32位。如这个参数和dwMaximumSizeHigh都是零,就用磁盘文件的实际长度。
  • lpName:String,指定文件映射对象的名字。如存在这个名字的一个映射,函数就会打开它。用vbNullString可以创建一个无名的文件映射。
  • 返回值调用CreateFileMapping的时候可能会出现的GetLastError的相应错误:
ERROR_FILE_INVALID (错误_文件_无效)如果企图创建一个零长度的文件映射
ERROR_INVALID_HANDLE(错误_无效_处理) 内存空间的命名和现有的内存映射,互斥量信号量临界区有同名
ERROR_ALREADY_EXISTS(错误或已经存在)表示内存空间命名已经存在

 

3、MapViewofFile()

     MapViewOfFile是计算机函数,功能是将一个文件映射对象映射到当前应用程序的地址空间。MapViewOfFileEx允许我们指定一个基本地址来进行映射。

LPVOID MapViewOfFile(HANDLE hFileMappingObject,DWORD dwDesiredAccess,     DWORD dwFileOffsetHigh,     DWORD dwFileOffsetLow,      DWORD dwNumberOfBytesToMap  
);

 

  • 参数1:hFileMappingObjectCreateFileMapping()或OpenFileMapping()返回的文件映像对象句柄。
  • 参数2:dwDesiredAccess 映射对象的文件数据的访问方式,而且同样要与CreateFileMapping()函数所设置的保护属性相匹配。 可取以下值:
FILE_MAP_ALL_ACCESS等价于CreateFileMapping的 FILE_MAP_WRITE|FILE_MAP_READ. 文件映射对象被创建时必须指定PAGE_READWRITE 选项.
FILE_MAP_COPY可以读取和写入文件.写入操作会导致系统为该页面创建一份副本.在调用CreateFileMapping时必须传入PAGE_WRITECOPY保护属性.
FILE_MAP_EXECUTE可以将文件中的数据作为代码来执行.在调用CreateFileMapping时可以传入PAGE_EXECUTE_READWRITE或PAGE_EXECUTE_READ保护属性.
FILE_MAP_READ可以读取文件.在调用CreateFileMapping时可以传入PAGE_READONLY或PAGE_READWRITE保护属性.
FILE_MAP_WRITE可以读取和写入文件.在调用CreateFileMapping时必须传入PAGE_READWRITE保护属性.
  • 参数3:dwFileOffsetHigh 表示文件映射起始偏移的高32位.
  • 参数4:dwFileOffsetLow 表示文件映射起始偏移的低32位.(64KB对齐不是必须的)
  • 参数5:dwNumberOfBytes 指定映射文件的字节数.

 

4、UNmapViewofFile()

在当前应用程序的内存地址空间解除对一个文件映射对象的映射。

BOOL UnmapViewOfFile(LPCVOID lpBaseAddress   // address where mapped view begins
);

 

  • lpBaseAddress Long,指定要解除映射的一个文件映射的基准地址。这个地址是早先用MapViewOfFile函数获得的。
  • 返回值Bool,非零表示成功,零表示失败。可以通过GetLastError()获取错误代码。

5、CloseHandle()

CloseHandle包括文件、文件映射、进程、线程、安全和同步对象等。涉及文件处理时,这个函数通常与vb的close命令相似。应尽可能的使用close,因为它支持vb的差错控制

BOOL CloseHandle(HANDLE hObject
);
  • hObject :代表一个已打开对象handle。
  • 返回值

   TRUE:执行成功;

     FALSE:执行失败,可以调用GetLastError()获知失败原因。

6、OpenFileMapping

OpenFileMapping是打开一个现成的文件映射对象的函数。

HANDLE OpenFileMapping(DWORD dwDesiredAccess,  // access mode  BOOL bInheritHandle,    // inherit flag  LPCTSTR lpName          // pointer to name of file-mapping object
);
  • 返回值零表示出错,可以设置GetLastError。
  • dwDesiredAccess是指带有前缀FILE_MAP_???的一个常数。参考MapViewOfFile函数dwDesiredAccess参数的说明。
FILE_MAP_ALL_ACCESS等价于CreateFileMapping的 FILE_MAP_WRITE|FILE_MAP_READ. 文件映射对象被创建时必须指定PAGE_READWRITE 选项.
FILE_MAP_COPY 可以读取和写入文件.写入操作会导致系统为该页面创建一份副本.在调用CreateFileMapping时必须传入PAGE_WRITECOPY保护属性.
FILE_MAP_EXECUTE可以将文件中的数据作为代码来执行.在调用CreateFileMapping时可以传入PAGE_EXECUTE_READWRITE或PAGE_EXECUTE_READ保护属性.
FILE_MAP_READ可以读取文件.在调用CreateFileMapping时可以传入PAGE_READONLY或PAGE_READWRITE保护属性.
FILE_MAP_WRITE可以读取和写入文件.在调用CreateFileMapping时必须传入PAGE_READWRITE保护属性.
  • bInheritHandle Long,如这个函数返回的句柄能由当前进程启动的新进程继承,则这个参数为TRUE。
  • lpName String,指定要打开的文件映射对象名称。

实例1:

通过加载特定文件中的类容,将其显示在文件编辑框中。环境搭建,需要在软件的exe文件的目录中添加一个.txt文件的文本文档。

内存文件映射的代码:

bool CMFC内存映射技术Dlg::LoadFile(CString strFileName)
{HANDLE hFile, hMapping;//定义一个点创建文件和文件映射的句柄void *basepointer;//定义一个指针变量,通过指针读操作内存if ((hFile = CreateFile(strFileName,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_FLAG_SEQUENTIAL_SCAN,0)) == INVALID_HANDLE_VALUE)//创建文件对象//用来打开已经存在的文件{AfxMessageBox(_T("Could not open file"));return FALSE;}if (!(hMapping = CreateFileMapping(hFile,0,PAGE_READONLY,0,0,NULL)))//创建文件映射对象{AfxMessageBox(_T("Mapping failed"));CloseHandle(hFile);return FALSE;}if (!(basepointer = MapViewOfFile(hMapping,FILE_MAP_READ,0,0,0)))//文件通过映射文件映射到内存{AfxMessageBox(_T("View failed"));CloseHandle(hFile);CloseHandle(hMapping);}m_strText = (LPTSTR)basepointer;//将文件的数据映射到进程的地址空间的指针转化为字符串的指针。UnmapViewOfFile(basepointer); //从进程的地址空间撤销对文件数据的映射CloseHandle(hFile);// 关闭文件对象CloseHandle(hMapping);//关闭文件映射对象return true;
}

 

实例2:

内存映射文件_共享数据,两个进程之间进行数据交换,有进程A通过内存映射文件技术将输入放入到内存中,之后由进程B将数据取出来显示。

进程A的源码:

  1. 在进程的主界面的初始化函数中创建文件映射对象和内存指针
    m_hMapObject = CreateFileMapping((HANDLE)0xffffffff,NULL,PAGE_READWRITE,0,0x1000,_T("shared_memory"));
    if (!m_hMapObject)
    {AfxMessageBox(_T("Unable to create shared memory file"));return FALSE;
    }
    m_pszMapView = (LPTSTR)MapViewOfFile(m_hMapObject,FILE_MAP_WRITE,0,0,0);
    if (!m_pszMapView)
    {AfxMessageBox(_T("Unable to map shared memory file"));return FALSE;
    }
  2. 将界面中的数值写入到内存中
void CDemoADlg::OnBnClickedSend()
{// TODO:  在此添加控件通知处理程序代码UpdateData();lstrcpy(m_pszMapView,m_strSend);
}

进程B源码

1、在进程的主界面的初始化函数中打开文件映射对象和内存指针

m_hMapObject = OpenFileMapping(FILE_MAP_READ,FALSE , _T("shared_memory"));
if (!m_hMapObject)
{AfxMessageBox(_T("Can`t open  shared memory file"));return FALSE;
}
m_pszMapView = (LPTSTR)MapViewOfFile(m_hMapObject, FILE_MAP_READ, 0, 0, 0);
if (!m_pszMapView)
{AfxMessageBox(_T("Unable to map shared memory file"));return FALSE;
}
SetTimer(0x10,500,NULL);

2、通过定时器获取内存地址中的数值

void CDemoBDlg::OnTimer(UINT_PTR nIDEvent)
{// TODO:  在此添加消息处理程序代码和/或调用默认值m_strText = m_pszMapView;UpdateData(FALSE);CDialogEx::OnTimer(nIDEvent);
}

注意:此一文主要是记录小编的笔记,有些事网上凑的,若有侵权,请联系删除!

http://www.xdnf.cn/news/11454.html

相关文章:

  • 软件工程专业值得考的8个证书
  • 使用C#判断字符串中是否包含中文字符
  • 【目标检测】58、目标检测中的正负样本分配策略总结
  • GaussDB数据类型转换介绍
  • pornstars java,Pornstar - QQ音乐-千万正版音乐海量无损曲库新歌热歌天天畅听的高品质音乐平台!...
  • 分享25个适合上班族的副业路子
  • Round Robin 算法
  • 常用的错误码介绍
  • 深入解析数码相机CCD坏点及噪点检测!【图解教程】
  • 容器化之-可视化镜像仓库管理(Harbor+阿里云oss)
  • 扒一扒那些叫欧拉的定理们(四)——平面几何欧拉定理美学鉴赏
  • PrepareStatement用法(附源码解析)
  • ubuntu使用VNC实现远程桌面
  • android drawtext 方法,8.2.13 drawText方法:绘制字符串
  • Windows系统字体优化方案(系统字体替换)
  • AAV相关研究最新进展(2023年5月)
  • 针对centos(Linux)多网卡bond绑定模式及其操作
  • LinearLayout
  • 29 | 分布式高可靠之流量控制:大禹治水,在疏不在堵
  • 【Android OpenGL开发】OpenGL ES与EGL介绍
  • ContentProvider的相关知识总结
  • 新加坡云服务器推荐 - 适合跨境外贸等业务
  • 2 v11补丁安装_老款macbook机型欺骗补丁强制安装macOS11 Big Sur图文详解
  • Linux下权限的修改-JDK的配置-文件的常见操作
  • Java学习 布局管理器之GridLayout(网格布局)
  • 企业最新几种好用的数据同步工具对比
  • Qt 多线程的几种实现方式
  • Linux系统三步安装QQ
  • C/C++网络编程
  • JSTL-核心标签库