Windows文件映射
几乎所有的应用程序都离不开对文件的操作,一般的步骤是打开文件,读写文件,关闭文件。但是,频繁的读写操作效率会很低,并且如果文件很大的情况,全部读入缓冲区也不现实,微软提供了一个叫映射文件的技术,可以完美解决上面的问题。我暂时的理解就是文件映射后得到一个指针,对这个指针进行任何操作(添加,修改数据)都是直接修改的文件。
用途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文件映射相关推荐
- 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 ...
- windows 内存映射文件
4.内存管理机制--内存映射文件 (Map) 和虚拟内存一样,内存映射文件可以用来保留一个进程地址区域:但是,与虚拟内存不同,它提交的不是物理内存或是虚拟页文件,而是硬盘上的文件. ·使用场合 ...
- 【samba】Wodows同步Linux文件|搭建共享文件服务器——在windows上映射网络驱动器
目录 Linux做samba服务器 Linux上的操作 windows上的操作 windows做samba服务器 windows上的操作 linux上的操作 错误记录 Linux Samba服务主配文 ...
- 【samba】Wodows同步Linux文件|搭建samba服务器共享文件——在windows上映射网络驱动器...
目录 Linux做samba服务器 Linux上的操作 windows上的操作 windows做samba服务器 windows上的操作 linux上的操作 错误记录 Linux Samba服务主配文 ...
- windows内存映射文件【学习笔记】
第一步:先创建一个文件,获得文件句柄 第二步 创建文件映射对象 第三步 映射到虚拟内存 lpAddr 就是当前虚拟内存的地址 第四步 使用虚拟内存地址,进行读写操作 写入文件不是即时的,在关闭资源的时 ...
- (代码篇)从基础文件IO说起虚拟内存,内存文件映射,零拷贝
上一篇讲解了基础文件IO的理论发展,这里结合java看看各项理论的具体实现. 传统IO-intsmaze 传统文件IO操作的基础代码如下: FileInputStream in = new FileI ...
- QT 进程间通信——文件映射
简述 在Windows中,在同一台机器上数据共享的最底层机制就是内存映射文件.在我们处理较大文件的时候,通常需要使用文件映射,即将物理地址中的文件数据映射到进程的虚拟地址中.通过文件映射之后,可以像操 ...
- LabVIEW将现有数据文件映射至TDMS数据文件格式
LabVIEW将现有数据文件映射至TDMS数据文件格式 在某些情况下,可能无法使用TDMS文件格式,例如客户或供应商指定必须使用某种格式存储数据.有些传统仪器可能会自动使用某种自定义格式提供数据输出文 ...
- windows文件副檔名說明
A 对象代码库文件 AAM Authorware shocked文件 AAS Authorware shocked包 ABF Adobe二进制屏幕字体 ABK CorelDRAW自动备份文件 ABS ...
- Python将文件映射到内存使用mmap.mmap()函数
1.如何将文件映射到内存 实际案例: (1)在访问某些二进制文件时,希望能把文件映射到内存中,可以实现随机访问.(framebuffer设备文件) (2)某些嵌入式设备,寄存器被编址到内存地址空间,我 ...
最新文章
- 实战测试SO_REUSEADDR选项
- 4.从单应矩阵中分离得到内参和外参(需要拍摄n=3张标定图片)
- python能print中文吗_win10中文版,python的print不能打印中文字符?
- 【Smartform】开发中报SSFCOMPOSER154错误原因分析
- Druid 在spring中的配置
- UC/OS-II的学习
- Direct 3D学习笔记(三)——光照与材质
- InTouch离线激活教程
- Java 建模: UML 工作簿:第 2 部分
- Tony的口胡呼呼(。-ω-)zzz
- java导入hbase_如何用java导入hbase.dat文件
- 叫号系统是否需要服务器,银行排队叫号方法及系统、服务器及存储介质
- 用ajax来上传图片,AJAX上传图片,使用ajaxupload
- 漂浮广告代码 php,JS带关闭按钮的网页漂浮广告代码
- 肿瘤基因检测的解读流程
- Unity视频播放器插件AVProVideo的使用
- 关于ramp texture的使用
- 计算机系统组成与基本工作原理
- 麦吉尔大学计算机工程的世界排名,「麦吉尔大学」2021qs世界排名_申请条件 - 言顶留学...
- CSS3炫酷发光文字 ,自定义色彩