分段分页机制&虚拟地址映射过程

分段分页机制&虚拟地址映射过程

分页:系统初始化时,类似于大小相等的固定分区,会将内存划分为很小的区块,称作页,而操作系统会为每一个进程分别维护一个页表,则进程根据这个页表可以实现加载到内存上页的不连续。

分段:加载进程时,将进程根据段加载,一个进程可以被分为多个段,操作系统会为每个进程维护一个段表,则加载的进程可以根据这个段表在虚拟内存上不连续的占据多个段。

 

MMU:内存管理单元,可以将逻辑地址映射为物理地址,即进行地址转换。

转换过程:先通过分段机制将一个逻辑地址转换为线性地址再通过分页机制将线性地址转换为物理地址。

 

分段机制的实现:

分段机制可以将虚拟地址转换为线性地址

段是虚拟地址空间的基本单位,所以仅仅靠一个段寄存器DS来确定一个基地址是远远不够的,至少还得描述段的长度,以及一些权限信息,所以这里有一个结构体,这个段描述符结构体包括三个方面的信息:

  1. 段的基地址:在线性地址空间中段的起始位置
  2. 段的大小:段内可以使用的最大偏移量
  3. 段的权限:段的一些保护属性,例如段是否可以读或者写。

上面的结构体可以叫做段描述符,多个段描述符组成的表叫做段描述符表

分段分页机制&虚拟地址映射过程_第1张图片

 

其中DS是16位数据段寄存器,其中前13位表示段描述符表的下标,共有2^13(8192)个段描述符,其中12个系统默认使用,所以用户只有8180个,剩下3位,第一位表示这个段描述符表是全局的还是局部的,如果为0表示为GDTR(全局段描述符表),为1表示为LDTR(局部段描述符表),第二位和第三位结合起来表示权限,00表示最高权限,11表示最低权限。

 

一个虚拟地址可以通过“段基地址+偏移量”的方式转换为线性地址,但是,由于绝大多数硬件平台都不支持段机制,只支持分页机制,所以为了让 Linux 具有更好的可移植性,我们需要去掉段机制而只使用分页机制。

但是软件都遵循着向前兼容的特点,所以段机制还得保留着,所以linux设计让段的基地址直接为0,让偏移量直接等于线性地址,而且偏移量还规定着小于4G,这刚好是线性地址空间的大小,也就是说让虚拟地址直接映射到线性地址,巧妙的将段机制问题处理了。

 

分页机制的实现:

分页机制将线性地址再转换为物理地址

分页机制由CR0寄存器中的PG位启用当PG=1,启动分页机制,通过二级页面映射将线性地址转换为物理地址,当PG=0,禁止分页机制,则直接将线性地址当作物理地址使用。

分页机制管理的对象是固定大小的存储块,称之为“页”,分页机制把整个线性地址空间及整个物理地址空间都看成由页组成,在线性地址空间中的任何一页,可以映射为物理地址空间中的任何一页(我们把物理空间中的一页叫做一个页面)

 

二级页表结构:

两级表结构的第一级称作页目录,存储在一个4k大小的页面中,CR3寄存器指向页目录的起始位置,页目录表共2^10(1024)个表项,每个表项4个字节,并指向第二级表也叫做页表,也刚好存储在一个4k大小的页面中,包含2^10(1024)个表项,每个表项包含一个页的物理基地址。

我们通过这样的方式,将线性地址的前10位来产生第一级表的索引,再通过线性地址的中10位来产生第二级表的索引。

通俗的讲就是通过线性地址的前10位确定在哪一个页目录上,再通过中10位确定是这个页目录中的具体哪一张页,再通过后12位确定其在这张表中的偏移,刚好2^12等于4K,也就是一张页的大小。

分段分页机制&虚拟地址映射过程_第2张图片

 

从这里我们可以算一算,页目录中有1024个页目录项,每个页目录项中又有1024个页,也就是说有1024*1024 = 1M的页,也就是内存大概可以划分100W左右数量的页,其中每个页大小为4K,所以虚拟内存空间大小正好为1M*4K = 4G

 

页面高级缓存机制:

由于在分页情况下,每次存储器访问都要经过两级页表映射,这就大大降低了访问速度。所以,为了提高速度,就出现了最近存取页面的高速缓存机制,它自动保存32项处理器最近访问的页面地址,因此,可以覆盖128K字节的存储器地址。当进行存储器访问时,先检查要访问的页面是否在高速缓存中,如果在,就不必经过两级访问了,如果不在,再进行两级访问。平均来说,页面高速缓存大约有98%的命中率,也就是说每次访问存储器时,只有2%的情况必须访问两级分页机构。这就大大加快了速度。

 

扩展分页:

从奔腾处理器开始,Intel处理器引进了扩展分页,它允许页的大小为4MB。
在扩展分页的情况下,分页机制把32位线性地址分成两个域:最高10位的目录域和其余22位的偏移量。

 

你可能感兴趣的:(Linux,网络)