【操作系统】分段、分页机制的理解

起因是上《操作系统高级教程》时,突然发现对这块的知识已经混沌了,所以重新总结下。
参考:
https://blog.csdn.net/yzy1103203312/article/details/78529067
https://blog.csdn.net/qq_32740495/article/details/102924136

一、为何需要分段

在8086处理器诞生之前,内存寻址方式就是直接访问物理地址(实模式)。8086处理器为了寻址1M的内存空间,把地址总线扩展到了20位。但是,ALU的宽度只有16位,即ALU不能计算20位的地址。为了解决这个问题,从而引入了分段机制

二、IA32框架的内存寻址

1.三类地址

IA32的三类地址如下:

  • 逻辑地址机器语言指令用这类地址指定一个操作数的地址或一条指令的地址,最原始的地址就是逻辑地址。
  • 线性地址:将逻辑地址经过分段机制转换之后,便得到了线性地址,每个线性地址都由一个段基址和段内偏移量组成
  • 物理地址:线性地址经过分页单元的处理之后得到一个实际物理地址,也就是内存单元的实际地址,用于芯片级内存单元寻址。

地址空间:操作系统给每个进程用的一段连续的虚拟内存空间。这个地址范围不是真实的,是虚拟地址的范围,有时甚至会超过实际物理内存的大小。

2.三类地址的转化

以上3类地址通过MMU(内存管理单元)来进行转换。其中MMU处理时包含2个过程,分段和分页。在这里简单的说明下具体过程:

  1. 当一条机器指令给出一个地址时,这时候的地址便是逻辑地址
  2. 为了得到线性地址,需要从相应的段寄存器中取出16位的段标识符(段选择符),通过这个段标识符可以得到一个段基址。然后将得到的段基址与指令中的地址相加,从而得到一个线性地址
  3. 有了线性地址之后,再通过分页单元得到实际的物理地址
    【操作系统】分段、分页机制的理解_第1张图片

三、分段

1.硬件中的分段

段是虚拟地址空间的基本单位,分段机制必须把虚拟地址空间的一个地址转换为线性地址空间的一个线性地址。
为了实现这种映射,仅仅用段寄存器来确定一个基地址是不够的,至少还得描述段的长度,并且还需要段的一些其他信息,比如访问权之类。所以,这里需要的是一个数据结构——段描述符,它包括三个方面的内容:

  • 段的基地址(Base Address):在线性地址空间中段的起始地址。
  • 段的界限(Limit):在虚拟地址空间中,段内可以使用的最大偏移量。
  • 段的保护属性(Attribute):表示段的特性。例如,该段是否可被读出或写入,或者该段是否作为一个程序来执行,以及段的特权级等等。

多个段描述符组成的表称为段描述符表。

逻辑地址的段寄存器中的值提供段描述符,然后从段描述符中得到段基址段界限,然后加上逻辑地址的偏移量,就得到了线性地址,线性地址通过分页机制得到物理地址。

2.Linux的分段

为了支持分段,8086处理器设置了四个段寄存器:CS, DS, SS, ES。每个段寄存器都是16位的,都包含着相应段的基址。访存指令中的地址也是16位的,但是,在送入地址总线之前,CPU先把它与某个段寄存器内的值按以下方式相加:

实际物理地址 = (段寄存器地址 << 4) + (指令访存地址)

这四个段寄存器的段首地址均是0,也就是说,段首地址+逻辑地址=线性地址,这个公式里面的段首地址为0,也就意味着在linux中,逻辑地址=线性地址,这就是linux的分段技术。

四、分页

对于物理内存,分页单元把它分为固定长度的页框(page frame),每一个页框包含一个页(page)。对于虚拟地址空间,也把它分为一个个的页。为了访问每一个物理页,需要有一个页表,记录每个物理页的起始地址,简单说通过页表就可以将一个虚拟内存中的页与具体的物理页一一对应起来。虚拟地址可以分为两部分,页号和页内偏移,页号为页表的索引,得到页的基地址后,加上偏移地址就可以得到具体的物理地址。

以32位环境为例,虚拟地址空间为4G,一般一页为4KB,这样4G内存可以分为1M个页,由于每个页表项需要4个字节来描述,因此一共需要4M的存储空间,因为每个进程都有自己的页表,所以1个进程就需要4M的存储空间。

你可能感兴趣的:(#,操作系统,学校课程,linux)