其为每个进程都提供了一个独立的‘互不干扰的空间。
1)将内存看做缓存,内存中存储此时正在运行的数据,其他数据存到磁盘,当需要使用时再换入内存,内存不够时将不用的换出到磁盘。
2)为每个进程提供了一致的地址空间,便于管理。
3)保护每个进程空间不被破坏。
分段机制下虚拟地址由两部分组成段选择子和段偏移量。
分段机制下就不得不提段表这种数据结构,其包括段基地址及段最大偏移量。
通过段选择子中的段号在段表中找到当前段真实段基地址,找到之后段基地址 + 段偏移量即为所求(段偏移量大于最大偏移量时会出现segment fault)。
如下图所示,若要查找段3偏移量为200的虚拟地址,我们可以计算出其物理地址为 段三基地址5000 + 段偏移量200 = 5200
Linux使用的时分页的方式。
OS将物理内存分为一块一块大小相同的页(一般为4K)。之前提到的OS可以将长时间不用的那些页面换出到磁盘上,需要时再换进内存,如此可以提高物理内存的利用率,这部分换出、换入的最小单位为1页。
分页存储需要一个被称为页表的数据结构,其中每一条数据含当前虚拟页号所对应的物理页号。
虚拟地址分为两部分,页号 + 页偏移量
虚拟地址 -> 物理地址过程如下:
首先通过虚拟页号从页表中找到当前虚拟地址对应的物理页号,然后通过物理页号,直到了物理页号也就直到了其基地址用基地址 + 偏移量即为所求。
由于我们事先已经知晓每页大小为4k,因此用物理页号 * 4k即为起始地址。
由于一页大小为4KB,因此其最大偏移量亦为4K,因此32位操作系统的情况下,低12位为页偏移量,高20位为页号。
以32位系统为例,其最大虚拟内存为4GB,如果按照每页4K大小,则共有4G / 4K = 1M个页表项,若每个页表项需要4字节(32位嘛)存储,则每个页表大小为4MB,貌似不大,但是需要注意的是需要为每一个进程都创建1个4MB大小的页表,这是一个特别大的开销。
因此采用多级页表的方式(也就是说对页表再分页),例如二级页表。
我们将4MB大小的页表分为1024个大小为4KB的页,每条记录占4B,使用4KB即可存储,将存储页表数据的页表成为页目录表。
使用二级页表情况下的虚拟地址为页目录表号(10位) + 页目录表偏移量(10位) + 页表偏移量(12位)
首先通过页目录表号通过页目录表找到其页表对应的基地址,再加上页目录表偏移量找到当前页的基地址,使用该基地址 + 页表偏移量即为所求。
对于页目录表而言其所管理的内存最多不超过1024页,因此10位的页目录号是刚好的,此外对于每一页中存1024条页表数据,因此10位页目录表偏移量也正好。在加上12位的页偏移量正好32位。
对于64位操作系统,linux采用的是4级目录。