1.内存寻址
处理器历史
- Intel 4004 4位的微处理器
- Intel 8008 8位的微处理器 可以通过两个次寄存器来访问16位的内存地址,共有2^16个地址也就是64K范围内的地址空间
- Intel 8086 16位的微处理器
- 引入 段,:ALU的宽度和地址总线宽度不同
- 16位的内部地址(高12位和段寄存器16位内容相加再结合剩下的4位凑成20位地址)
- 地址总线20位,1M地址空间
- Intel 80286 16位的微处理器
- 地址总线达到了24位,16M个单元的内存空间
- 引入保护模式,不能直接从段寄存器中获得基地址了
- Intel 80386 32位的微处理器 开启80x86
- 地址总线达到了32位,4G个单元的内存空间
80x86寄存器
- 8个32位通用寄存器 EAX EBX ECX EDX EBP ESP ESI EDI
- 4个16位的段寄存器 CS DS SS ES
- 80x86以前 段寄存器存放段的基地址
- 80x86以后 段寄存器存放段选择符(段描述符在段表中的索引+TL:决定从LDT还是GDT中惦相应的段描述符+RPL:请求者的特权级别,Linux只使用了最高和最低即内核和用户特权级别)
- 指令指针寄存器和标志寄存器 EIP EFLAGS
- 4个32位控制寄存器 CR0 CR1 CR2 CR3 用于分页机制 控制允许分页和及目录基址等
物理地址 线性地址 虚拟地址(逻辑地址)
- 虚拟地址 段:偏移 表示
- 线性地址 范围为0-4GB的地址空间
- 地址转换通过MMU内存管理单元
- 虚拟地址 -> 线性地址 段机制实现
- 线性地址 -> 物理地址 页机制实现
段机制
段表和段描述符
- 段描述符
- 8字节的数表示(基地址 段长 保护属性)
- 32位的基地址 20位的段界限(长度)
- 描述符表
- 保护模式下还有其他三种描述符表(全局描述符表GDT,中断描述符表IDT,局部描述符表LDT),专门设置GDTR,IDTR,LDTR寄存器存放表的基地址和长度加速访问
- 地址转换和保护(转换成线性地址)
- 段寄存器装入选择符,地址偏移量装入寄存器
- 段描述符放入段描述符高速寄存器
- 段描述符中的基址和偏移量相加得到线性地址
- Linux中的段机制(有些处理器不支持段机制)
- 基地址设为0 段长4GB 即偏移量 = 线性地址
- 因为1.数据段和代码段需要分别创建 2.Linux的内核特权和用户特权划分 所以需要创建四个段 内核:数据|代码段 用户:数据|代码段
- 系统启动 设置了段寄存器和全局描述符表
页机制
页 页表和页大小
- 将线性地址划分成若干大小的片称为页
- 线性地址空间分页 和 物理地址空间分页
- 80x86 页大小4KB
- 页表
- 页表项 4字节 1.物理页面的基地址 2. 页的属性
- 4GB线性地址空间可以被划分1M个4KB大小的页
- 两级页表 解决页表项连续存放需要4M空间的问题
- 两级页表 线性地址结构 页目录 + 页 + 页内偏移
- 页表项
- 物理页基地址
- 地址转换(线性地址转成物理地址)
- 获取目录项的地址
- 获取页表的地址
- 获取页表项的地址
- 取出物理基地址加上线性地址中的偏移地址形成物理地址
- 页面高速缓存TLB
- 通过缓存页表项来减少两次访问内存
Linux中的分页
三级分页
- 页总目录PDG,页中间目录PMD,页表PT
网友评论