分页时,Loader 的线性地址为什么要与物理地址相同?

分页时,Loader 的线性地址为什么要与物理地址相同?

分页机制(Paging)启用之前Loader(引导程序或内核启动代码) 需要使用 物理地址进行访问,而在分页启用后,它的 线性地址需要与物理地址一致,这样可以 确保分页机制生效后,代码仍然可以正常运行


1. 什么是分页?

  • 分页(Paging)CPU 通过页表将线性地址(Linear Address)转换为物理地址(Physical Address) 的过程。
  • 开启分页前,CPU 直接使用 物理地址 访问内存。
  • 开启分页后,CPU 访问的 虚拟地址(线性地址) 需要通过 页表转换物理地址

但在启用分页的瞬间,CPU 仍然要继续执行代码,因此必须确保代码地址在启用分页前后保持一致,否则会出现访问错误。


2. 为什么 Loader 线性地址 = 物理地址?

分页启用(开启 CR0.PG)的瞬间

  • Loader(内核代码)仍然在运行
  • 指令地址不能改变,否则 CPU 会找不到指令,导致崩溃!

因此,必须保证 Loader 在开启分页前后的地址是一样的
[
\text{线性地址} = \text{物理地址}
]
这样 分页前后的代码地址不变,保证 CPU 能继续正常执行代码。


3. 具体实现方式

(1)开启分页前

  • 使用物理地址访问(未开启分页)
  • 代码仍然在 物理地址 0x100000 运行(假设 Loader 在 1MB 处)。

(2)设置页表

建立一个 “恒等映射(Identity Mapping)”:

  • 页表设置 线性地址 = 物理地址
  • 例如:
    页目录:0x00000000 → 指向 0x00000000(恒等映射)
    页目录:0x00100000 → 指向 0x00100000(恒等映射)
    
    这样:
    线性地址 0x100000 → 物理地址 0x100000
    

(3)开启分页

  • write_cr3(页目录地址); // 设置 CR3
  • write_cr0(read_cr0() | 0x80000000); // 开启 CR0.PG
  • 此时,CPU 进入分页模式,但地址转换仍然映射到相同的物理地址

(4)跳转到新的虚拟地址

  • 如果 Loader 需要被映射到更高地址(例如 0xC0000000),则可以:
    1. 建立新的页表映射
      线性地址 0xC0000000 → 物理地址 0x100000
      
    2. 跳转到 0xC0000000,然后释放恒等映射

4. 为什么不直接使用虚拟地址?

如果 分页前 代码运行在 虚拟地址 0xC0000000

  • 在启用分页前0xC0000000 不是一个有效的物理地址,导致 CPU 找不到代码,程序崩溃!
  • 必须先建立页表,然后再跳转到高地址

5. 结论

开启分页前,Loader 只能访问物理地址
开启分页时,必须确保 线性地址 = 物理地址,防止 CPU 找不到代码
分页启用后,Loader 可以跳转到更高的虚拟地址(如 0xC0000000)。

🚀 “恒等映射” 是分页启用的关键,确保 CPU 在启用分页后仍然能正确执行指令! 🎯

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值