知道共享内存吗?
额,是把同一块内存映射到两个进程的地址空间?。。。。。。
(还不如说不知道)
内存映射
内存映射主要应用于三种情况:
- 系统使用内存映射文件载入EXE,DLL文件。这节省了大量页交换文件的空间以及程序启动时间。
- 开发人员使用内存映射文件来访问磁盘上的数据文件,这使得我们避免直接对文件I/O操作和文件内容的缓存
- 通过使用内存映射文件,可以实现不同进程间的共享数据(进程间共享内存通信)
创建一个内存映射文件相当于先预订一块地址空间区域,然后再给区域调拨物理存储器。唯一的不同在于内存映射文件的物理存储器来自磁盘上的文件,而不是系统的页交换文件中分配(内存)。
转载可执行文件:
CreateProcess时,系统执行以下步骤:
1、找到exe文件位置
2、系统创建新的内核对象
3、系统为新进程创建私有地址空间
4、系统在地址空间预定一块足够大区域容纳exe文件,默认基地址0x400000。
5、系统会标注exe所在的地址空间区域。表面该区域的后备物理存储器来自磁盘的文件而不是来自系统的页交换文件。(即在磁盘,不在内存)
6、当系统把exe文件映射到进程地址空间后,会访问exe的一个段,获取DLL加载信息,系统调用LoadLibrary()加载每个DLL。每次加载DLL步骤都类似上述4、5。
区别是exe是第一个加载的模块,基地址不会被占用,而DLL的基地址可能已经被占用,需要对DLL进行重定位,修改部分指令。
系统同样会标注DLL的地址空间区域,表明该区域的后备物理存储器来自磁盘的DLL文件,而不是系统的页交换文件。但是如果执行了重定位,则会标注被修改的部分物理存储器被映射到了页交换文件。
同一可执行文件/dll 的多个实例不会共享全局/静态数据
通过内存映射文件,同一应用程序的多个实例可以共享内存中的代码和数据。
系统通过写时复制特性防止应用程序的一个实例修改了数据页面的全部变量,影响其他实例。
写时复制:任何程序试图写入内存映射文件时,系统首先截获,然后为应用程序分配一块新内存页,赋值页面内容,最后让应用程序写入刚分配的新内存页。
使用内存映射文件
三个步骤:
1、创建或者打开一个文件的内核对象,该对象标识了我们想要用作为内存映射文件的