1. 内存寻址
- 逻辑地址: 通过一个段(segment) 和 一个偏移量(offset)来表示
- 线性地址: 也称虚拟地址, 是一个32bit的无符号整数, 可以用来表征4G的地址空间
- 物理地址: 用于内存芯片级的内存单元的寻址, 由32bit ~ 36bit 无符号整数来表示
- 逻辑地址转换示意图:
2. 硬件中的分段
intel 8086系列主要有两种工作模式:实模式 和 保护模式
2.1 段选择器和段寄存器
- 一个逻辑地址由一个段标志符(16bit)和一个指定段内的相对地址偏移量(32bit)组成。
- 段选择符中 index 表示选择的段在 gdt (全局描述符表)或者 ldt (局部描述符表)中的位置, TI 表示 gdt/ldt 表, RPL 表示权限
- 段寄存器的唯一目的: 存放段选择器, 可以用来方便的查找段选择符
2.2 段描述符
- 段由一个8字节的段描述符来表示, 描述了段的特征。 而段描述符又存放在gdt 或者 ldt表中。
2.3 快速访问描述符
- 为了加速从逻辑地址到线性地址的转换, 可以借助通过一个非编程寄存器直接存储段描述符(8字节)来解决这个问题
2.4 分段单元
逻辑地址到线性地址转换示意图:
3. Linux中的分段
- Linux 只有在8086结构下才使用分段,其他时候都是仅使用分页
- Linux 下逻辑地址和线性地址是一致的, 所有的段都是从0x00000000开始, 偏移量字段和相应的线性地址的值保持一致
3.1 Linux GDT
- 单处理器系统中只有一个GDT, 而多处理器系统中每个CPU对应一个GDT, 所有GDT 表都存放在cpu_gdt_table 数组中
3.2 Linux LDT
一般只有在需要模拟windows程序时候, 才会用到ldt
4. 硬件中的分页
- 分页单元将线性地址转换为物理地址, 需要注意权限问题
4.1 常规分页
- 使用二级映射模式, 减少了每个进程页表所需的RAM数量, 支持4KB分页大小
4.2 扩展分页
- 允许页框大小为4MB
4.3 硬件保护方案
- 与页和页表有关的特权级别, 在页目录项中表征为 User/Supervisor 标志
4.4 常规分页举例
4.5 物理地址扩展PAE 分页机制
- 由于大型服务器需要大于4GB的RAM来同时运行多个进程, intel 通过扩展32bit地址总线到 36bit实现 64GB 的寻址能力, 因而, 相应的需要引入一个新的分页机制, 将32bit线性地址转化为 36 bit 物理地址。
- 具体方式, 通过引入新级别的页目录表, 原先的 3 段, 现在变成 4 段。
本质上来讲, 就是从原先页目录表和页表中拿了2bit独立成一个pdpt表。
显然, 他没有扩展进程的线性地址空间, 但是他却允许内核使用64G (此时有 36bit 物理地址总线)的RAM, 增加了系统中进程的数量
4.6 64位系统中的分页
ps: 32bit 的两级分页模型并不适合64bit系统, 需要引入3 ~ 4 级分页模型
4.7 硬件高速缓存
- 为了缩小CPU 和 RAM 之间的速度的不匹配, 引入了硬件高速缓存内存的概念
- 他基于局部性原理: 最近最常使用的相邻地址在最近的将来又被用到的可能性极大
- 以行为单位, 缓存
- 通写和回写策略etc
4.8 转换后援缓冲器TLB
- 用来加速线性地址转换
5. Linux 中的分页
(ps: 这部分写的比较简略, 具体细节还是看书吧,有一堆api 看了不想写, 还有一些东西太复杂, 没仔细看。。。。)
1. 采用4级分页模型, 每部分的大小和具体的计算机的体系结构有关
5.1 线性地址字段
- PAGE_SHIFT, PMD_SHIFT,PUD_SHIFT, PGDIR_SHIFT, etc
5.2 进程页表
用http://blog.csdn.net/zhyh1435589631/article/details/50989569这篇博客里面的这张图感觉应该好理解些
5.3 TLB的处理
关键是提高命中率和同步