LINUX内存管理-内核寻址
理论(・∀・(・∀・(・∀・*)
主要参考书目:《深入理解LINUX内核(第三版)》
ps:理论相关说明以32位为例
内核寻址
内存寻址过程:
1 |
|
分段
先放一张图说明分段单元将逻辑地址(16位段选择符:32位偏移)转化为线性地址的过程
段选择符结构:
1 |
|
- 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内存管理-内核寻址/