系统在创建一个进程时需要赋予它虚拟地址空间,不同进程之间的虚拟地址空间是独立的,对于32位平台每个进程的虚拟地址空间为4G,进程A和进程B如果都在自己的虚拟地址空间中访问地址为0x12345678的内容时,A和B访问到的都是自己私有数据,因为他们在映射到物理存储器时是不同的地址,当然4G的虚拟地址空间也是有划分的,有用户模式分区(一般代码和数据映射到该处),内核模式分区,空指针赋值分区,64KB禁入分区,
在赋予进程地址空间时,虚拟地址并未映射到具体的物理地址,需要使用函数VirtualAlloc来预订,然后再调用VirtualAlloc(和预定时参数不一样)调拨物理存储器(部分数据可以先不调拨,避免占用大量的物理存储器),最后程序才能开始执行。由于内存空间是有限的,因此我们使用磁盘来充当“内存”,即物理存储器,该部分“内存”被称为页面交换文件。
我们运行一个程序时先分配虚拟地址空间,然后预订物理存储器,再调拨物理存储器,再将该进程的代码和数据复制到已调拨的物理存储器(页面交换文件),但是如果这样做不仅会使得页面交换文件变得很庞大,而且效率上会很低,因此我们使用一种称为“内存映射文件”的文件镜象来用作虚拟地址空间对应的物理存储器,这样在载入一个dll或者exe文件时,系统会自动预订地址空间区域并把文件映像映射到该区域,从而加快程序的启动速度。在windows中虚拟空间中以段来组织,比如.text段,.data段,这些段叫做虚拟段。CPU在访问数据如果不在内存中,那操作系统将磁盘中的数据读到内存中,所以操作系统需要知道虚拟空间和可执行文件之间的映射关系,这种关系在操作系统内部通过一个数据结构来维护,操作系统在出现页错误后会查询这个数据结构,然后找到空页面所在的虚拟段,计算出页面在可执行文件中的偏移,然后在物理内存中分配一个物理页面,将数据载入物理页,并建立虚拟页和物理页的映射关系。
进程一开始执行会发生缺页错误,因为此时的数据全在页面交换文件或者内存映射文件中,操作系统需要把数据载入到内存在才能执行