系统如何定义进程获得的虚拟内存部分



如果有32位系统(假定为Windows),则虚拟地址空间为4GB。因此CPu可以生成这个范围内的任何地址。那么一个进程不应该也能处理这个范围内的任何地方吗?据说每个进程都有自己的私有虚拟地址空间。那么系统是如何促进这一点的呢?

换句话说,CPU生成一个32位地址,并将其转换为物理地址。现在,CPU如何知道特定进程必须只寻址虚拟地址空间(其私有虚拟地址空间)的特定部分。

假设一个进程从其私有虚拟地址空间中寻址一个地址,会发生什么?

程序必须在Windows上调用VirtualAlloc()来告诉操作系统它想要使用一块虚拟内存。通常由于从堆中分配内存或加载DLL而间接调用。

操作系统反过来设置页面映射表,CPU使用这些表将程序中使用的虚拟地址转换为物理RAM地址,作为其地址总线引脚上的输出。每当CPU在虚拟内存地址读取或写入数据或执行代码时,就会发生三种不寻常的事情之一:

  • 如果页面映射表中没有条目,则CPU会引发一般保护故障陷阱。操作系统验证地址是否无效并终止程序
  • 如果页面还没有映射到RAM,则CPU引发页面故障陷阱。操作系统会找到一页未使用的RAM,必要时会交换掉一页已使用的RAM。并确保内容有效,必要时从文件或分页文件加载内容。并更新表条目,使其现在具有RAM页面的物理地址。执行恢复正常
  • CPU验证是否允许访问该页面。对标记为只读的页的写入或对标记为不执行的页中的指令的执行会生成一般保护故障陷阱。操作系统终止程序

每个进程都有自己的一组页面映射表,确保一个进程无法访问另一个进程使用的RAM页面。除非特别要求共享,否则从可执行文件和内存映射文件加载的代码页是常见的。上下文开关加载CR2寄存器,即包含页面映射表地址的CPU寄存器。

因此,在任何情况下,进程都不能在其私有虚拟地址空间之外寻址内存,因为缺少匹配的分页表条目,这确保了程序的终止。

整个4GB地址空间可供进程使用(尽管通常上半部分是为内核数据保留的),MMU将其部分映射到物理内存。进程不能"超出"其地址空间(允许使用所有4GB的地址空间),但如果其中的某些部分尚未映射到物理内存,则会引发硬件异常。

地址空间被认为是私有的,因为操作系统在任务切换时会更改MMU的设置,因此每个进程都会看到不同的独立内存布局(尽管部分地址空间可以与其他进程共享)。

最新更新