内存管理(一):CPU寻址
内存管理(一):内存寻址
总线
总线分工:
- 数据总线:负责数据实际传输
- 地址总线:负责传输数据地址
- 控制总线:负责传输控制信号
取数据的时候CPU通过地址总线传输地址给内存,内存返回的数据通过数据总线传递给CPU
数据总线和地址总线决定因素:
数据总线:CPU位数 -> 寄存器位数 -> 数据总线位数
地址总线:内存地址信号引脚数 -> 地址总线位数
大部分情况下:CPU位数 != 地址线位数,像8086CPU数据总线有16条,地址线有20条
年份 | 1978 | 1985 | 1993-2006 | 200至今 |
---|---|---|---|---|
处理器CPU | 8086 | 80386 | Pentium系列 | Core系列 |
CPU位数 | 16 | 32 | 32、64 | 64 |
地址总线位数 | 20 | 32 | 32、36、39 | 40、48可扩展 |
处理器名字:如果是Intel 32位体系结构叫x86,Intel 64位扩展体系结构叫X86-64
8086的分段寻址
CPU存储的位数是16位,它的寄存器只有16位,但是地址总线却有20位。如果不做特殊处理的话,CPU只能访问64KB内存,后面的内存无法访问到。
分段寻址
解决方法:分段寻址
- 分段,将1MB内存分成多个64KB的段
- 通过段基址寄存器(16位)存储存储一段在内存中的基地址
- 段基地址左移 4 位并加上段内偏移,从而找到内存中的地址
- 想要访问其他段,那么段寄存器只需要存储其他段的段基址即可
注:ip寄存器是指令寄存器,用来存储需要执行的指令在段中的偏移的。如果需要访问数据,则需要将数据的段内偏移加载到通用寄存器中。
8086的分段寻址
由于一个程序也需要分段:
CPU有三个寄存器用来存储不同段的基址:
- CS(Code Segment)寄存器
- DS(Data Segment)寄存器
- SS(Stack Segment)寄存器
注意:还有一个ES寄存器(附加段寄存器),这篇就先不给出来
访问数据的时候:(DS << 4) + 段内偏移
访问栈的时候:(SS << 4) + 段内偏移
访问代码的时候:(CS << 4) + 段内偏移
注意:每个程序自己的三个段基地址是不同的,CPU切换不同程序的时候,会切换段基地址寄存器的值
实模式的缺点
这个时期的8086处理器,所有操作都是在真实物理内存上,这个时候还没有操作系统这么一说。也没有权限控制,只要你驱动接口,就可以随意更改内存。这就是Linux所谓的“实模式”,安全性差。
一个程序有可能会不小心访问其他程序的数据,不安全,没有内存保护。
80386的分段寻址
80386位处理器32位,地址总线有32根,可以访问4G的内存。不需要采用实模式,而是使用保护模式。当然由于80386是一个开放包容的处理器,它的保护模式是兼容实模式的。
注:80386实现分段是为了兼容,现代操作系统都不用分段寻址了,分段寻址只是一个过渡。
保护模式的分段寻址
80386是32位处理器,8个通用寄存器从16位变为32位。
IP寄存器(16位)变为EIP寄存器(32位)
段寄存器不再存储段起始地址,而是存储段选择子
- 段表中有段长度,如果段内偏移大于段长度则说明访问段外的内存,非法访问内存
- 段表存储了权限,比如可读可写等,权限控制更加灵活
- 保护模式是可以兼容实模式的,32位的寄存器既可以存储32位也能存储16位。
GDT和LDT
GDT(Global Descriptor Table)是全局描述符表。
LDT(Local Descriptor Table)局部描述符表。
LDT属于程序,GDT属于系统,同一台计算机上所有程序共享一个GDT。GDTR是GDT的寄存器,LDTR是LDT的寄存器
分段寻址缺陷
容易产生内存碎片
当时8086处理器引入分段的目的是为了解决16位CPU寻址20位内存问题。但是现代操作系统都不用分段了。
现代操作系统为了兼容都保留了分段,但是基本都不用了。将段的起始地址设置位内存起始地址,将段长度设置为最大。把整个内存看成一段。
现代操作系统使用分页寻址。
分页寻址
分页
- 将物理内存分为多个大小相等的物理页(Physical Page,PP),页的大小可以是:4KB,8KB,16KB..
- 将每个程序的虚拟内存,分为多个大小相等的虚拟页(Virtual Page,VP),虚拟页大小等于物理页大小
- 通过页表来确定虚拟页对应哪个物理页
- 每个程序都有自己的页表,感觉自己拥有一个独立的虚拟内存
地址转换
在虚拟地址空间中程序使用的是虚拟内存,那么CPU该如何通过虚拟地址来获取真实地址呢?
- 虚拟地址由 虚拟页号 + 页内偏移 组成
- 通过虚拟页号去页表中查询物理页号
- 物理页号 + 页内偏移就是真实地址了
- 页内偏移选择的位数是根据页大小来确定的,比如页大小是64字节,那么虚拟地址的前6位做位页内偏移,2^6 = 64
分页寻址相关的硬件
- 页表基址寄存器(PTBR):用于存储页表在内存中的基地址,用于找到页表在内存中的位置
- 内存管理单元(MMU):CPU将虚拟地址给到MMU,MMU将虚拟地址转换为物理地址
MMU工作方式:
- 通过页表基址寄存器,找到页表的起始地址
- 通过虚拟页号和页表起始地址,找到页表项的位置
- 读取物理页号
- 物理页号+页内偏移就是物理地址
多级页表
- 解决单个页表项过多、页表过大可以采用多级页表
- 通过一级页表去找二级页表的页表起始地址,通过二级页号到二级页表中找到二级页表的页表项