简单介绍
- 一个内存区对象(section object)代表一个可以被分享的内存的节。一个进程可以使用一个内存区对象来与另一个进程分享它的一个内存地址空间(内存节)。内存区对象。内存区对象另外提供了一种机制,可以将一个文件映射到一个进程的地址空间中。
每一个内存区对象有一个或者多个对应的视图。一个内存区对象的一个视图是这个对象在这个进程中可以访问的一部分。创建一个内存区对象的一个视图又称为“映射内存区对象的一个视图”。每一个操作内存区对象的内容的进程都有其自己的一个视图。一个进程可以有多个不同的视图,对应同一个或者很多个内存区对象。
文件后备和页面文件后备内存区对象
- 所有的内存节(memory section),无论是临时的或者是永久的,都必须有一个后备文件,用来包含所共享的内存区对象。当我们创建一个内存区对象,可以指定数据文件,这样的内存区对象称为“文件后备的内存区对象”,如果没有指定后备文件,这个内存区对象的后备文件为“系统页面文件”,被称为“页面文件后备的内存区对象”。只有文件后备的内存区对象的数据才有可能在磁盘上永久存储。
一个文件为后备文件的内存区对象代表了磁盘上的一个实际的文件的内容,或者称为内存映射文件。任何在给定的文件后备的内存区对象的范围内的内存访问,都对应访问绑定的文件的位置。如果进程将一个文件映射为read-only,任何从视图的读取操作都被转换为从文件的读取。相似的,写操作也是类似的。这些视图的虚拟地址空间没有使用页面文件的任何空间。一个文件后备的内存区对象可以被映射为copy-on-write。此时任何的写操作都不是写到实际的文件中,而是写到一份私有地址空间的拷贝中,在该视图被取消映射之后,所失去所做的修改。
一个页面文件后备的内存区对象的后备文件为页面文件,而不是普通的磁盘文件,此时所做的内存操作,在内存区对象被删除之后都将被抛弃。页面文件后备的内存区对象可以用作进程间共享内存段。
无论是什么样的内存区对象,都可以被两个进程共享(可能不是相同的虚拟地址)。
管理内存区对象
- 驱动可以通过调用ZwCreateSection 来创建一个内存区对象,返回内存区对象的句柄。返回的内存区对象可以通过ZwOpenSection 打开。
为了在当前进程的地址空间中访问内存区对象对应的数据,必须映射一个视图。驱动可以使用ZwMapViewOfSection 映射一个视图到当前进程的地址空间中。SectionOffset 指定在内存区对象内的偏移,ViewSize 指定需要映射的大小。
Protect 参数指定允许在视图视图上进行的操作,PAGE_READONLY,PAGE_READWRITE等等。
直到视图对应的虚拟地址范围被访问,不会为视图分配真正的物理内存。第一次访问该地址范围将导致一个页面错误,系统申请页面以对应该内存位置。如果内存区对象是文件后备的,读取文件对应位置到内存中。
在使用完视图之后,调用ZwUnmapViewOfSection 取消映射。不使用内存区对象之后,调用ZwClose 关闭内存区对象。在对应的视图被映射,而且没有其它的映射操作之后,可以立即调用ZwClose 函数,视图和内存区对象将持续存在直到视图被取消映射。这是被建议的操作,因为这降低了驱动关闭句柄失败的风险。