LINUX内存管理-内核寻址

理论(・∀・(・∀・(・∀・*)

主要参考书目:《深入理解LINUX内核(第三版)》

ps:理论相关说明以32位为例

内核寻址

内存寻址过程:

1
逻辑地址->[分段单元]->线性地址->[分页单元]->逻辑地址

分段

先放一张图说明分段单元将逻辑地址(16位段选择符:32位偏移)转化为线性地址的过程

段选择符结构:

1
2
3
4
15            3  2  0
+-------------+--+----+
| index |TI|RPL |
+-------------+--+----+
  • index:GDT或LDT中段描述符的入口
  • TI:1表示段描述符在LDT中,0表示段描述符在GDT中
  • RPL:请求者特权级,0(内核态)或3(用户态)

段描述符结构:

  • Base:段首字节的线性地址
  • G:粒度标记,0则段大小一字节为单位,1则以4086字节为单位
  • Limit:段中最后一个内存单元的偏移量
  • S:系统标志,0表示系统段(如LDT)
  • Type:段类型和存取权限(代码段,数据段,任务状态段)
  • DPL:特权级
  • P:0表示不在主存中(Linux总是将P置1,因为不把整个段换到磁盘中)
  • D或B:数据段或代码段
  • AVL:略

Linux中的分段

80x86结构使用以下分段:

相应的段选择符由__USER_CS、__KERNEL_CS、__USER_DS、__KERNEL_DS定义,寻址时只需要把相应的宏装入cs段寄存器或者ds段寄存器就行

所有段都从0开始,说明Linux中逻辑地址和线性地址是一样的

实际寻址时只需要使用cs或者ds寄存器中的段选择符+地址偏移就可以进行,所以我们日常看到的地址实际上都是逻辑地址中的偏移

分页

cr0寄存器中的PG标志表示分页是否开启,PG=0时线性地址直接被解释为物理地址

一些分页机制

常规分页

分页单元将线性地址转化为物理地址的过程如下:

10+10+12=32

页目录项和页表项结构:

  • Present:页是否在主存中
  • Field:页框物理地址高20位(一页4KB,页框基地址0x1000对齐)
  • Accessed:分页单元寻址时使用,当页被交换出去时被操作系统使用
  • Dirty:页被修改
  • Read/Write:存取权限
  • User/Supervisor:特权级
  • PCD和PWT标志:控制硬件高速缓存处理页或页表的方式
  • Page Size:应用于页目录项,置1表示页目录指向2MB或4MB的页框
  • Global:应用于页表项,防止常用页被从TLB中刷新出去,cr4的PGE标志置1时使用
扩展分页

页框大小为4MB而不是4KB

10+22=32

目录项和正常分页基本相同,除了:

  • Page Size必须设置
  • 32位物理地址(offset)只有最高10位有意义,因为4MB的页大小0x400000对齐

设置cr4寄存器的PSE标志能使扩展分页和常规分页共存

物理地址扩展(PAE)分页机制

32位线性地址可以使用4GB的物理地址,为了使用增加的物理地址(64GB)产生了PAE

设置cr4的PAE标志激活PAE,页目录项中的Page Size标志启用大尺寸页(启用PAE时为2MB)

  • 引入PDPT,改变cr3中的值
  • 同一线性地址可能对应不同物理地址

Linux中的分页

32位64位通用

  • 32位:页上级目录和页中间目录全为0
  • 启用PAE的32位:三级页表,页全局目录对应PDPT,取消页上级目录

一些加快分页的硬件

  • 硬件高速缓存
  • 转换后援缓冲器(TLB)

LINUX内存管理-内核寻址
http://akaieurus.github.io/2023/08/05/LINUX内存管理-内核寻址/
作者
Eurus
发布于
2023年8月5日
许可协议