C++前序——(1)虚拟地址空间

一、前言

以前的程序,都是直接运行在物理内存上的,即程序在运行时访问的地址都是物理地址。这种方式带来的问题就是:如何把有限的物理内存分配给这么多程序使用呢?

C++前序——(1)虚拟地址空间

与此同时,这种内存分配策略也带来几个问题:

(1) 程序间的地址不隔离,恶意程序可能会借此损坏正常程序的数据。

(2) 内存使用效率低,由于内存大小有限,当剩余的内存不够装载接下来要运行的程序的时候,正在运行的程序需要暂停换出到磁盘,以空出足够的内存来,等它运行完了再换回来。这样大量的数据进进出出,导致内存的使用效率非常低下。

(3) 程序运行的地址不确定,程序在装载运行时,都需要占用内存上的一块空间,这个空间的位置是不确定的。但是,程序在编写时,很多数据或是指令跳转时的目标地址都是确定的,这个问题给程序的编写带来不小的问题。

所以,为了解决以上的三个问题,增加了中间层——虚拟地址,提供了一种间接访问物理内存的访问方法。

二、虚拟地址

为了解决上述的几个问题,虚拟地址就出现了。为了隔离每个程序,每一个程序都有自己的地址空间、CPU(当然,只是看起来是这样),每一个程序都可以不用管其他的程序,就像它占据了整个计算机。

1.地址空间

(1) 物理地址空间

物理地址空间是实实在在存在于计算机中的,它和地址空间的地址长度有关。如果计算机是32位的,即计算机的地址总线有32条,那么物理空间就有4GB。4GB的物理空间中,只有内存的512MB有效,其他的是外存部分。

(2) 虚拟地址空间

虚拟地址空间其实是人为想象出来的地址空间,这个地址空间的大小有CPU的位数(硬件的寻址空间大小)决定,32位CPU的虚拟地址空间大小为4GB,64位CPU的虚拟地址空间大小为17179869184GB(看起来很大了吧,可是以后或许还有更大的,因为在32位时人们就觉得“够了”...)

每一个进程都有自己的虚拟地址空间,这样使得每一个进程都只能访问自己的地址空间而互不影响。当进程在访问自己的虚拟地址空间时,实际上访问的是它映射在物理地址空间的那一部分。

具体的映射方式,就是内存分段、分页管理中的内容了。

C++前序——(1)虚拟地址空间

那么,在32位的虚拟地址空间中,4GB的空间是否程序都可以使用呢?

2.虚拟地址空间的分布

其实,整个虚拟地址空间都是由操作系统来管理的,所以进程只能使用那些操作系统分配给它的空间。同时,操作系统留有一部分给自己使用。

32位操作系统下虚拟地址空间的分布

C++前序——(1)虚拟地址空间



其中,内核中的ZONE_DMA如果进行了配置,则程序进入内存就不需要进入寄存器。