几乎所有的应用程序都离不开对文件的操作,一般的步骤是打开文件,读写文件,关闭文件。但是,频繁的读写操作效率会很低,并且如果文件很大的情况,全部读入缓冲区也不现实,微软提供了一个叫映射文件的技术,可以完美解决上面的问题。我暂时的理解就是文件映射后得到一个指针,对这个指针进行任何操作(添加,修改数据)都是直接修改的文件。

用途1:使用内存映射文件加载和执行exe和dll,可以大大节省页面文件空间(暂未研究)
用途2:使用内存映射文件访问磁盘数据,不必IO操作,不必缓存
用途3:在同一台计算机上的多个进程来共享数据。windows下提供的其他进程间通信的方法基本都是基于内存映射文件实现的。

使用内存映射文件需要以下步骤:
1)创建或打开一个文件内核对象,用于告知磁盘上需要用作内存映射文件
2)创建文件映射内核对象,告诉系统文件的大小以及访问文件的方式
3)将文件的全部或部分映射到进程的地址空间中
映射完成后需要按照以下步骤清除
1)撤销文件映射内核对象的映像
2)关闭文件映射内核对象
3)关闭文件内核对象

创建或打开文件对象
HANDLE  CreateFileA(
    _In_ LPCSTR lpFileName,//文件名
    _In_ DWORD dwDesiredAccess,//如何访问  (GENERIC_READ|GENERIC_WRITE或组合)
    _In_ DWORD dwShareMode,//文件共享方式(FILE_SHARED_READ|FILE_SHARED_WRITE或组合或0)
    _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,//安全属性,内核继承相关
    _In_ DWORD dwCreationDisposition,//
    _In_ DWORD dwFlagsAndAttributes,
    _In_opt_ HANDLE hTemplateFile
    );

dwCreationDispositionLong,下述常数之一:
CREATE_NEW 创建文件;如文件存在则会出错
CREATE_ALWAYS 创建文件,会改写前一个文件
OPEN_EXISTING 文件必须已经存在。由设备提出要求
OPEN_ALWAYS 如文件不存在则创建它
TRUNCATE_EXISTING 将现有文件清空
参数见:https://baike.baidu.com/item/CreateFile/9621657?fr=aladdin

注:CreateFile失败会返回INVALID_HANDLE_VALUE

创建文件映射对象,失败返回NULL
LPVOID CreateFileMappingA(
    _In_     HANDLE hFile,//上面CreateFile的返回值
    _In_opt_ LPSECURITY_ATTRIBUTES lpFileMappingAttributes,//安全属性
    _In_     DWORD flProtect,//保护模式。PAGE_READONLY,PAGE_READWRITE,PAGE_WRITECOPY
    _In_     DWORD dwMaximumSizeHigh,//映射文件长度的高位
    _In_     DWORD dwMaximumSizeLow,//映射文件长度的低位,两个组合成映射文件的长度
    _In_opt_ LPCSTR lpName//内核名字,即命名对象
    );

将文件数据映射到进城地址空间
MapViewOfFile(
    _In_ HANDLE hFileMappingObject,//上面CreateFileMapping的返回值
    _In_ DWORD dwDesiredAccess,//权限,FILE_MAP_WRITE,FILE_MAP_READ,FILE_MAP_ALL_ACCESS(与FILE_MAP_WRITE相同),FILE_MAP_COPY
    _In_ DWORD dwFileOffsetHigh,//映射文件的起始位置高位
    _In_ DWORD dwFileOffsetLow,//映射文件的起始位置低位,组合起来则是起始位置
    _In_ SIZE_T dwNumberOfBytesToMap//此次需要映射的长度,设为0则全部映射
    );
注:偏移量需要是Windows分配粒度的整数倍,(目前一直都是64K)

撤销就比较简单了,就是UnMapViewOfFile与CloseHandle

两个进程通过内存文件映射共享内存的例子,简单拖了个界面,open则是进行初始化的一些创建操作,close则是清除文件映射对象,read获取值,write写入值

初始化部分代码:

        if (mapView){UnmapViewOfFile(mapView);mapView = NULL;}hFile = ::CreateFileA("D:/1.txt", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);if (hFile == INVALID_HANDLE_VALUE){MessageBox("CreateFile error");return ;}HANDLE hFileMapping = ::CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 1024,"FILEMAP");if (::GetLastError() == ERROR_ALREADY_EXISTS){MessageBox("filemapping exists");//CloseHandle(hFileMapping);}if (!hFileMapping){MessageBox("CreateFileMapping error");return ;}else{mapView = MapViewOfFile(hFileMapping, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);CloseHandle(hFileMapping);}

清除部分

UnmapViewOfFile(mapView);
mapView = NULL;
CloseHandle(hFile);

读取部分:

if (!mapView)
{MessageBox("mapview not open");
}
char *p = (char*)mapView;
GetDlgItem(IDC_EDIT1)->SetWindowTextA(p);

由于MapViewOfFile的返回值是一个void*类型,所以可以自己进行转化,对得到的这个指针进行操作就像是在操作内存一般简单,不过实际上对它的所有操作都是在修改了文件

写入部分:

if (!mapView)
{MessageBox("mapview closed");return;
}CString p;
GetDlgItemText(IDC_EDIT1,p);
memset(mapView, 0, 1024);
//SetEndOfFile必须在撤销视图的映像并关闭了文件映射对象之后才能调用,不然就会返回FALSE
//使用GetLastError返回ERROR_USER_MAPPED_FILE,表明不能在与文件映射对象相关联的对象上执行此操作
//此处只是简单的进行清0处理
//SetFilePointer(hFile, p.GetLength(),NULL, FILE_BEGIN);
//BOOL bRet = SetEndOfFile(hFile);
memcpy(mapView, p.GetBuffer(0), p.GetLength());
p.ReleaseBuffer();

上面清0的原因是如果一开始文件内容比较长,然后写入了一个短一点的字符串,再次读取后会读取到后面的未被修改的数据
例:源字符串 abc123,之后一个进程写入123,另一个进程再读时会得到123123

Windows文件映射相关推荐

  1. linux windows文件映射,WINDOWS的共享文件夹映射到linux上

    环境: 1.有两台机器,A:Windows(win 7)和B:Linux(centos) 2.A:192.168.0.101   B:192.168.0.102 3.创建yum源 目的:windows ...

  2. windows 内存映射文件

    4.内存管理机制--内存映射文件 (Map)    和虚拟内存一样,内存映射文件可以用来保留一个进程地址区域:但是,与虚拟内存不同,它提交的不是物理内存或是虚拟页文件,而是硬盘上的文件. ·使用场合 ...

  3. 【samba】Wodows同步Linux文件|搭建共享文件服务器——在windows上映射网络驱动器

    目录 Linux做samba服务器 Linux上的操作 windows上的操作 windows做samba服务器 windows上的操作 linux上的操作 错误记录 Linux Samba服务主配文 ...

  4. 【samba】Wodows同步Linux文件|搭建samba服务器共享文件——在windows上映射网络驱动器...

    目录 Linux做samba服务器 Linux上的操作 windows上的操作 windows做samba服务器 windows上的操作 linux上的操作 错误记录 Linux Samba服务主配文 ...

  5. windows内存映射文件【学习笔记】

    第一步:先创建一个文件,获得文件句柄 第二步 创建文件映射对象 第三步 映射到虚拟内存 lpAddr 就是当前虚拟内存的地址 第四步 使用虚拟内存地址,进行读写操作 写入文件不是即时的,在关闭资源的时 ...

  6. (代码篇)从基础文件IO说起虚拟内存,内存文件映射,零拷贝

    上一篇讲解了基础文件IO的理论发展,这里结合java看看各项理论的具体实现. 传统IO-intsmaze 传统文件IO操作的基础代码如下: FileInputStream in = new FileI ...

  7. QT 进程间通信——文件映射

    简述 在Windows中,在同一台机器上数据共享的最底层机制就是内存映射文件.在我们处理较大文件的时候,通常需要使用文件映射,即将物理地址中的文件数据映射到进程的虚拟地址中.通过文件映射之后,可以像操 ...

  8. LabVIEW将现有数据文件映射至TDMS数据文件格式

    LabVIEW将现有数据文件映射至TDMS数据文件格式 在某些情况下,可能无法使用TDMS文件格式,例如客户或供应商指定必须使用某种格式存储数据.有些传统仪器可能会自动使用某种自定义格式提供数据输出文 ...

  9. windows文件副檔名說明

    A 对象代码库文件 AAM Authorware shocked文件 AAS Authorware shocked包 ABF Adobe二进制屏幕字体 ABK CorelDRAW自动备份文件 ABS ...

  10. Python将文件映射到内存使用mmap.mmap()函数

    1.如何将文件映射到内存 实际案例: (1)在访问某些二进制文件时,希望能把文件映射到内存中,可以实现随机访问.(framebuffer设备文件) (2)某些嵌入式设备,寄存器被编址到内存地址空间,我 ...

最新文章

  1. 实战测试SO_REUSEADDR选项
  2. 4.从单应矩阵中分离得到内参和外参(需要拍摄n=3张标定图片)
  3. python能print中文吗_win10中文版,python的print不能打印中文字符?
  4. 【Smartform】开发中报SSFCOMPOSER154错误原因分析
  5. Druid 在spring中的配置
  6. UC/OS-II的学习
  7. Direct 3D学习笔记(三)——光照与材质
  8. InTouch离线激活教程
  9. Java 建模: UML 工作簿:第 2 部分
  10. Tony的口胡呼呼(。-ω-)zzz
  11. java导入hbase_如何用java导入hbase.dat文件
  12. 叫号系统是否需要服务器,银行排队叫号方法及系统、服务器及存储介质
  13. 用ajax来上传图片,AJAX上传图片,使用ajaxupload
  14. 漂浮广告代码 php,JS带关闭按钮的网页漂浮广告代码
  15. 肿瘤基因检测的解读流程
  16. Unity视频播放器插件AVProVideo的使用
  17. 关于ramp texture的使用
  18. 计算机系统组成与基本工作原理
  19. 麦吉尔大学计算机工程的世界排名,「麦吉尔大学」2021qs世界排名_申请条件 - 言顶留学...
  20. CSS3炫酷发光文字 ,自定义色彩

热门文章

  1. 微信授权 php laraval,Laravel中微信网页授权
  2. 怎么单凭手机进行低成本制作网页?今日让我分享一下经验
  3. 企业如何自建MDM 移动设备管理平台
  4. 什么是噪声,白噪声,加性噪声,乘性噪声
  5. ps 改变图片中的文字
  6. 企业微信4.0:上下游功能上线,用一款APP连接所有企业组织和用户
  7. 【diannaoxitong】word安全模式怎么解除?word安全模式快速解除方法
  8. 中医经典《伤寒论》-原文
  9. CentOS官网 安装包下载
  10. 01 官网下载各种CentOS教程(超详细版)