从零到一手写操作系统(四、硬件知识 2)地址转换)

image.png

如果追忆会荡起涟漪,那么今天的秋红落叶和晴空万里都归你
https://aeneag.xyz
微信公众号:技术乱舞
艾恩凝

手写操作系统目录

硬件知识

4.2)地址转换

4.2.1)虚拟地址

拿C写的代码举例来说,反汇编完成后,可以查看他的汇编代码,会有虚拟地址,这些地址并不是真正运行在机器上的内存,每个程序都有自己的虚拟地址,程序与程序之间并没有关联,这部分是由链接器做的。

经过编译步骤后,就需要链接成可执行文件才可以运行,而链接器的主要工作就是把多个代码模块组装在一起,并解决模块之间的引用,即处理程序代码间的地址引用,形成程序运行的静态内存空间视图。只不过这个地址是虚拟而统一的,而根据操作系统的不同,这个虚拟地址空间的定义也许不同,应用软件开发人员无需关心,由开发工具链给自动处理了。

4.2.2)物理地址

字面意思,就是这个地址是真实存在的,其实物理地址在逻辑上,就是一个数据,在硬件中就是一个在总线上的信号,简单理解就是这个地址就是内存中真正的地址。比如内存 是 0x30000000开始,这个0x30000000就是真正的物理地址,这个地址上可以真正的存放数据。

4.2.3)虚拟地址->物理地址

要实现转换,软件效率太低,所以引入了MMU,内存管理单元。
019mmu.png

上图中展示了 MMU 通过地址关系转换表,将 0x800000x84000 的虚拟地址空间转换成 0x100000x14000 的物理地址空间,而地址关系转换表本身则是放物理内存中。

如果是虚拟地址一一对应物理地址,那么物理地址也会很快用完。新的方案又出现了,把虚拟地址空间和物理地址空间都分成同等大小的块,也称为页,按照虚拟页和物理页进行转换。根据软件配置不同,这个页的大小可以设置为 4KB、2MB、4MB、1GB,这样就进入了现代内存管理模式——分页模型
020分页.png

分页之后,页大小是固定的,虚拟页地址会对应物理页地址。

4.2.4)MMU(内存管理单元)

MMU ,是用硬件电路逻辑实现的一个地址转换器件,它负责接受虚拟地址和地址关系转换表,以及输出物理地址。

根据实现方式的不同,MMU 可以是独立的芯片,也可以是集成在其它芯片内部的,比如集成在 CPU 内部,x86、ARM 系列的 CPU 就是将 MMU 集成在 CPU 核心中的。

x86 CPU 要想开启 MMU,就必须先开启保护模式或者长模式,实模式下是不能开启 MMU 的。

由于保护模式的内存模型是分段模型,它并不适合于 MMU 的分页模型,所以我们要使用保护模式的平坦模式,这样就绕过了分段模型。
021地址转换.png

程序代码中的虚拟地址,经过 CPU 的分段机制产生了线性地址,平坦模式和长模式下线性地址和虚拟地址是相等的。

不开启 MMU,在保护模式下可以关闭 MMU,这个线性地址就是物理地址。因为长模式下的分段弱化了地址空间的隔离,所以开启 MMU 是必须要做的,开启 MMU 才能访问内存地址空间。

4.2.5)MMU页表

022页表.png

第一个位段索引顶级页目录中一个项,该项指向一个中级页目录,然后用第二个位段去索引中级页目录中的一个项,该项指向一个页目录,再用第三个位段去索引页目录中的项,该项指向一个物理页地址,最后用第四个位段作该物理页内的偏移去访问物理内存。这就是 MMU 的工作流程。

简单说:虚拟地址有四块构成,第一块保存了下一个中间页目录地址,第二块保存了下一级的页表地址,第三块保存了物理页地址,第四块是偏移。

4.2.6)保护模式下的分页

分页模式的灵活性、通用性、安全性,是现代操作系统内存管理的基石,更是事实上的标准内存管理模型,现代商用操作系统都必须以此为基础实现虚拟内存功能模块。

32位的虚拟地址经过分段机制之后得到线性地址,又因为通常使用平坦模式,所以线性地址和虚拟地址是相同的。

保护模式下的分页大小通常有两种,一种是 4KB 大小的页,一种是 4MB 大小的页。分页大小的不同,会导致虚拟地址位段的分隔和页目录的层级不同,但虚拟页和物理页的大小始终是等同的。

MMU思想是一样的,但是每个芯片设计略有不同,

4.2.6.1)4KB分页

32 位虚拟地址被分为三个位段:页目录索引、页表索引、页内偏移,只有一级页目录,其中包含 1024 个条目 ,每个条目指向一个页表,每个页表中有 1024 个条目。其中一个条目就指向一个物理页,每个物理页 4KB。这正好是 4GB 地址空间。如下图所示。

0234kb.png

10 10 12

分页模式下的 CR3、页目录项、页表项的格式:
0244kb分页.png

前面不是说页目录1024个,页表1024个,然后1024个4kb物理页在,这样正好是4GB,页目录和页表是由一个32位4字节表示的,那么1024个4字节又是4kb,所以这就是4kb分页。

地址始终是 4KB 对齐的,所以低 12 位才可以另作它用,形成了页面的相关属性,如是否存在、是否可读可写、是用户页还是内核页、是否已写入、是否已访问等。

4.2.6.2)4MB分页

32 位虚拟地址被分为两个位段:页表索引、页内偏移,只有一级页目录,其中包含 1024 个条目。其中一个条目指向一个物理页,每个物理页 4MB,正好为 4GB 地址空间。
0254mb.png

而是指向一个 4KB 大小的页表,这个页表依然要 4KB 地址对齐,其中包含 1024 个页表项
0264mb分页.png

4MB 大小的页面下,页表项还是 4 字节 32 位,但只需要用高 10 位来保存物理页面的基地址就可以。因为每个物理页面都是 4MB,所以低 22 位始终为 0,为了兼容 4MB 页表项低 8 位和 4KB 页表项一样,只不过第 7 位变成了 PS 位,且必须为 1,而 PAT 位移到了 12 位。

4.2.7)长模式下的分页

长模式开启,必须开启分页模式,长模式下有4KB和2MB

4.2.7.1)4KB分页

027场模式4kb.png

顶级页目录、页目录指针、页目录、页表各占有 4KB 大小,其中各有 512 个条目,每个条目 8 字节 64 位大小

5 5 5 5 12 = 4GB。

虚拟地址 48 到 63 这 16 位是根据第 47 位来决定的,47 位为 1,它们就为 1,反之为 0,这是因为 x86 CPU 并没有实现全 64 位的地址总线,而是只实现了 48 位,但是 CPU 的寄存器却是 64 位的。
028.png

029.png

0304kb.png

4.2.7.2)2MB分页

031长模式2mb.png

顶级页目录、页目录指针、页目录各占有 4KB 大小,其中各有 512 个条目,每个条目 8 字节 64 位大小。

长模式下 2MB 和 4KB 分页的区别是,2MB 分页下是页目录项直接指向了 2MB 大小的物理页面,放弃了页表项,然后把虚拟地址的低 21 位作为页内偏移,21 位正好索引 2MB 大小的地址空间。
032.jpeg
033.png

4.2.8)MMU开启

  1. 使 CPU 进入保护模式或者长模式。
  2. 准备好页表数据,这包含顶级页目录,中间层页目录,页表,假定我们已经编写了代码,在物理内存中生成了这些数据。
  3. 把顶级页目录的物理内存地址赋值给 CR3 寄存器。
  4. 设置 CPU 的 CR0 的 PE 位为 1,这样就开启了 MMU。

假如地址 转换失败怎么办?

  1. MMU 停止转换地址。
  2. MMU 把转换失败的虚拟地址写入 CPU 的 CR2 寄存器。
  3. MMU 触发 CPU 的 14 号中断,使 CPU 停止执行当前指令。
  4. CPU 开始执行 14 号中断的处理代码,代码会检查原因,处理好页表数据返回。
  5. CPU 中断返回继续执行 MMU 地址转换失败时的指令。

手写操作系统目录


    


公众号'艾恩凝'
个人公众号
个人微信
个人微信
    吾心信其可行,
          则移山填海之难,
                  终有成功之日!
                                  ——孙文
    评论
    0 评论
avatar

取消