由于所有用户进程总的虚拟地址空间比可用的物理内存大很多,因此只有最常用的部分才与真实物理页帧关联。因此大多数程序只占用实际可用内存的一小部分。
一个进程虽然拥有3G虚拟内存访问权限,但是实际需要的内存可能很少,另外一个进程大部分的主体,比如代码段、只读数据段等并不需要实时驻留在内存中,因为这些内容是“死的”。因此内存映射的第一个作用就是只会将某一进程此刻需要的内存映射到物理内存,其他暂时不需要的内容交换到硬盘存储即可。当进程需要使用在硬盘中的内容或者需要动态申请内存时,操作系统会利用缺页操作,触发一次内存映射,将另外的物理内存映射进虚拟内存,供程序使用。
每个进程均有自己的内存映射表。任意一个时刻,在一个CPU上只有一个进程在运行。所以对于CPU而言,在此时刻,整个系统只存在一个4GB的虚拟地址空间,这个虚拟地址空间是面向此进程的。
当进程发生切换的时候,虚拟地址空间也随着切换。只有进行在运行的时候,其虚拟地址空间才被CPU所知。
在CPU眼中,只有一个虚拟地址空间存在。虚拟地址空间的变化,随着进程切换而变化。
虚拟内存中每个运行的进程无需关心实际内存是多大,分配内存会不会超出限制,哪些内存已经被其他进程占用等。这些都交由kernel的内存管理单元解决,暴露给进程的接口只有每个进程独有的虚拟地址空间。
一个新进程建立的时候,将会建立起自己的内存空间,此进程的数据,代码等从磁盘拷贝到自己的进程空间,哪些数据在哪里,都由进程控制表中的task_struct记录,task_struct中记录中一条链表,记录中内存空间的分配情况,哪些地址有数据,哪些地址无数据,哪些可读,哪些可写,都可以通过这个链表记录。
1.既然每个进程的内存空间都是一致而且固定的,所以链接器在链接可执行文件时,可以设定内存地址,而不用去管这些数据最终实际的内存地址,这是有独立内存空间的好处
2.当不同的进程使用同样的代码时,比如库文件中的代码,物理内存中可以只存储一份这样的代码,不同的进程只需要把自己的虚拟内存映射过去就可以了,节省内存
3.在程序需要分配连续的内存空间的时候,只需要在虚拟内存空间分配连续空间,而不需要实际物理内存的连续空间,可以利用碎片。
进程的时间片用完之后,当前正在进行的进程就会保留当前的状态进入到缓存当中,当再次轮训到该进程使用CPU时,才会出缓存中被读取出来。
物理内存1G和进程的虚拟内存没有直接关系,需要通过MMU进行管理和映射。