虚拟地址与物理地址

虚拟地址

        恰如其名,这个地址是虚拟的,与具体环境是解耦的,这样可以是程序员在编写程序时只需要关注代码逻辑本身,而不需要考虑地址分配。这些虚拟地址并不是真正运行在机器上的内存地址,每个程序的虚拟地址都是独立存在的,虚拟地址是逻辑上存在的一个数值。实际上我们在开发程序的过程中,软件程序经过编译后需要经过链接才能形成可执行程序,通过链接器将多个代码模块组装在一起,并解决模块之间的引用,即处理程序代码地址之间的引用问题,形成程序运行的静态内存空间视图。只不过这个地址是虚拟而统一的,而根据操作系统的不同,这个虚拟地址空间的定义也许不同,应用软件开发人员无需关心,由开发工具链给自动处理了。由于这虚拟地址是独立且统一的,所以各个公司开发的各个应用完全不用担心自己的内存空间被占用和改写。

物理地址

        顾名思义,就是真实存在的地址,物理地址在逻辑上也是一个数据,只不过这个数据会被地址译码器等电子器件变成电子信号,放在地址总线上,说明地址总线上的信号就代表了物理地址,地址总线电子信号的各种组合就可以选择到内存的储存单元,同时也可以选择其它设备的储存单元,如显卡中的显存、I/O 设备中的寄存器、网卡上的网络帧缓存器。

虚拟地址与物理地址相互转换

        通过上面的理解,我们知道,如果程序想要正常运行,必须将虚拟地址转换为物理地址,转换就需要一个转换结构或者转换函数,用软件的方式实现这个函数,效率比较低下,直接用硬件方式又不够灵活,于是就引入了软硬结合的方式——MMU(内存管理单元)。MMU 可以接受软件给出的地址对应关系数据,进行地址转换。

 

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

        如果将虚拟地址与物理地址一一对应,那么在实际开发过程中,我们会很快将物理地址给使用完,于是就引入了现代内存管理模式——分页模式,把虚拟地址空间和物理地址空间都分成同等大小的块,也称为页,按照虚拟页和物理页进行转换。根据软件配置不同,这个页的大小可以设置为 4KB、2MB、4MB、1GB

MMU

        MMU 即内存管理单元,是用硬件电路逻辑实现的一个地址转换器件,它负责接受虚拟地址和地址关系转换表,以及输出物理地址。根据实现方式的不同,MMU 可以是独立的芯片,也可以是集成在其它芯片内部的,比如集成在 CPU 内部,x86、ARM 系列的 CPU 就是将 MMU 集成在 CPU 核心中的。

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

        由于保护模式的内存模型是分段模型,它并不适合于 MMU 的分页模型,所以我们要使用保护模式的平坦模式,这样就绕过了分段模型。这个平坦模型和长模式下忽略段基址和段长度是异曲同工的。

         程序代码中的虚拟地址,经过 CPU 的分段机制产生了线性地址,平坦模式和长模式下线性地址和虚拟地址是相等的。如果不开启 MMU,在保护模式下可以关闭 MMU,这个线性地址就是物理地址。因为长模式下的分段弱化了地址空间的隔离,所以开启 MMU 是必须要做的,开启 MMU 才能访问内存地址空间

MMU页表

        页表是分级的,总体分为三个部分:一个顶级页目录,多个中级页目录,最后才是页表。

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

保护模式下的分页

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

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

4KB分页模式

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

        CR3 就是 CPU 的一个 32 位的寄存器,MMU 就是根据这个寄存器找到页目录的。下面,我们看看当前分页模式下的 CR3、页目录项、页表项的格式

        前面已说明此分页模式下,页目录有1024个,页表有1024个,每个物理页又是4kb物,这样正好是4GB,页目录和页表是由一个32位4字节表示的,那么1024个4字节又是4kb,所以这就是4kb分页。地址始终是 4KB 对齐的,所以低 12 位才可以另作它用,形成了页面的相关属性,如是否存在、是否可读可写、是用户页还是内核页、是否已写入、是否已访问等。

4MB分页

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

        CR3 还是 32 位的寄存器,只不过不再指向顶级页目录了,而是指向一个 4KB 大小的页表,这个页表依然要 4KB 地址对齐,其中包含 1024 个页表项。

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

长模式下的分页

        如果开启了长模式,则必须同时开启分页模式,分页大小通常也有两种,4KB 大小的页和 2MB 大小的页。

4KB分页

        该分页方式下,64 位虚拟地址被分为 6 个位段,分别是:保留位段,顶级页目录索引、页目录指针索引、页目录索引、页表索引、页内偏移,顶级页目录、页目录指针、页目录、页表各占有 4KB 大小,其中各有 512 个条目,每个条目 8 字节 64 位大小

        上面图中 CR3 已经变成 64 位的 CPU 的寄存器,它指向一个顶级页目录,里面的顶级页目项指向页目录指针,依次类推。需要注意的是,虚拟地址 48 到 63 这 16 位是根据第 47 位来决定的,47 位为 1,它们就为 1,反之为 0,这是因为 x86 CPU 并没有实现全 64 位的地址总线,而是只实现了 48 位,但是 CPU 的寄存器却是 64 位的。这种最高有效位填充的方式,即使后面扩展 CPU 的地址总线也不会有任何影响。

        长模式下的 4KB 分页下,由一个顶层目录、二级中间层目录和一层页表组成了 64 位地址翻译过程。顶级页目录项指向页目录指针页,页目录指针项指向页目录页,页目录项指向页表页,页表项指向一个 4KB 大小的物理页,各级页目录项中和页表项中依然存在各种属性位,这在图中已经说明。其中的 XD 位,可以控制代码页面是否能够运行。

2MB分页

        在这种分页方式下,64 位虚拟地址被分为 5 个位段 :保留位段、顶级页目录索引、页目录指针索引、页目录索引,页内偏移,顶级页目录、页目录指针、页目录各占有 4KB 大小,其中各有 512 个条目,每个条目 8 字节 64 位大小

 

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

        上图中没有了页表项,取而代之的是,页目录项中直接存放了 2MB 物理页基地址。由于物理页始终 2MB 对齐,所以其地址的低 21 位为 0,用于存放页面属性位

开启 MMU

要使用分页模式就必先开启 MMU,但是开启 MMU 的前提是 CPU 进入保护模式或者长模式。开启步骤如下:

1. 使 CPU 进入保护模式或者长模式。

2. 准备好页表数据,这包含顶级页目录,中间层页目录,页表,假定我们已经编写了代码,在物理内存中生成了这些数据。

3. 把顶级页目录的物理内存地址赋值给 CR3 寄存器。

4.设置 CPU 的 CR0 的 PE 位为 1,这样就开启了 MMU

MMU 地址转换失败

MMU 地址转换失败了怎么办呢?失败了既不能放行,也不是 reset,MMU 执行的操作如下:

1.MMU 停止转换地址。

2.MMU 把转换失败的虚拟地址写入 CPU 的 CR2 寄存器。

3.MMU 触发 CPU 的 14 号中断,使 CPU 停止执行当前指令。

4.CPU 开始执行 14 号中断的处理代码,代码会检查原因,处理好页表数据返回。

5.CPU 中断返回继续执行 MMU 地址转换失败时的指令。

  • 4
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值