|

分享源码
界面截图: |
|
是否带模块: |
纯源码 |
备注说明: |
- |
由于我看论坛上关于内存映射文件的帖子并不是很多,因此我决定分享一个。
内存映射的过程如下:
首先我们先使用CreateFile函数打开一个文件,然后获取它的句柄(HANDLE),只要这个句柄不是INVALID_HANDLE_VALUE(-1),那么接下来就只要考虑内存映射的问题了。
有了这个句柄后干什么呢?当然是读写了!
但是呢,这次的读写和往常不太一样了。
对于读取操作,我们先使用GetFileSizeEx获取这个文件的大小,然后将其分割为低32位和高32位两部分。
写入操作则是先清空文件中的所有内容,然后使用SetFilePointer+SetEndOfFile调整文件的大小。
接下来大体上都是一样的。
我们使用CreateFileMapping函数来创建一个内存映射对象,这样的话可以方便你访问整个文件,
如果映射对象的句柄不为NULL的话,接下来就可以使用MapViewOfFile函数来获取内存地址了,如果这个地址不为NULL的话,那么就说明我们已经成功一大半了。
接下来又要请出我们的老朋友RtlMoveMemory了,它是干什么的呢?
它其实是读写文件的关键,因为它的功能就是内存拷贝(因为文件已经映射到内存中了,所以这个函数就可以负责内存操作)!
接下来在关闭映射句柄和文件句柄前还需要使用UnmapViewOfFile来释放映射的地址,然后使用CloseHandle关闭映射句柄和文件句柄后读写操作可以说是就算是完成了。
此外,这种读写操作不需要使用传统的ReadFile,WriteFile及其扩展版本ReadFileEx,WriteFileEx,甚至它们的NT版本ZwReadFile,ZwWriteFile,NtReadFile,NtWriteFile都没有使用,你可能会问:
在读写过程中会不会使用易自带的 写到内存() ,或者WindowsAPI例如ReadProcessMemory,WriteProcessMemory呢,又或者使用汇编代码来读写内存呢?
问得好!不过实际上都没有(对于ReadProcessMemory,WriteProcessMemory,我甚至连它们的NT版本、64位NT版本都没有使用)。你可能会不敢相信,其实真正的读写操作全靠RtlMoveMemory!
这里我给大家解释一下:对于读取操作,我们只需要将MapViewOfFile返回的映射地址通过RtlMoveMemory转换成字节集就可以得到文件的数据了,写入操作则是相反。
不过需要注意以下几点:
1、读取时文件大小不能为0
2、对于读取操作,只能从文件开头开始读取,无法自定义读取位置,不支持设备
3、写入操作同理,只能从文件开头开始写入,无法自定义写入位置,不支持设备
4、为了防止映射失败,写入之前会清空文件中的现有数据,你可能需要自行备份数据
|
评分
-
查看全部评分
|