Intel 80386 存储器管理
有参考一些文章
一、存储器的管理
存储器的管理是一种硬件机制,微处理器在总线地址上对物理存储器进行寻址。但是,为了给程序提供比物理存储器容量更大的空间,就引入了虚拟存储器的概念,它在外存(比如磁盘)的支持来下实现,通常所说的虚拟地址称为逻辑地址。对80386来说,既有段的管理又有页的管理。对段和页的管理属于操作系统的职责,80386从硬件上提供管理机制。
总结一下会用到哪些机制:
机制 |
---|
段管理机制 |
段页管理直接 |
二级页表 |
快表 |
在存储管理的时候我们会用到寄存器,这里先概览一下。
80386微处理器共有7类34个寄存器,通用寄存器组、段寄存器、指令指针和标志寄存器、系统地址寄存器、控制寄存器、调试寄存器、测试寄存器。
前四类寄存器的示意图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YrP0FJQA-1651556465675)(C:\Users\15191\Desktop\ComputerScienceClassNote\OS\CPU\80386寄存器.png)]
二、Intel 80386 微处理器的三种工作方式
三种工作方式:
- 实地址方式
- 虚地址保护方式
- 虚拟8086方式。
1.实地址方式
386在硬件复位后处于该模式下,只能使用32位地址总线的低20位地址,寻址空间为1MB。
此时他就是一个8086/8088微处理器,不同的是它不仅可以运行8086/8088的全部指令,还可以运行32位的运算类指令。
系统初始化区在FFFFFFF0H-FFFFFFFFH存储区内。
设置此方式是为了与8086兼容,也可从实地址方式转变到保护虚地址方式。
物理地址由8386芯片地址引线送出的低的20位地址码,经过存储器译码后选择一个存储单元进行读写,物理地址可用5位的十六进制来表示20位的地址。
储器地址分段是把1MB 的存储器空间分成若干段,每段的容量最大为64KB,每个段首地址的高16位二进制代码就是该段的段号(称段基地址)。
存储器采用分段管理后,段地址存放在段寄存器CS、DS、SS、ES中,对段寄存器设置不同的值来使微处理器的段寄存器指向存储器中不同的段。
偏移地址是相对于某段首地址的段内偏移量。物理地址的形成,把段地址左移4 位得到段基地址,再加上偏移地址值就形成了20 位的物理地址。
2.虚地址保护方式
当Intel 80386/486 的**控制寄存器CR0的最低位为PE(Protection Enable)保护模式允许位,用来启动CPU进入虚地址保护方式。**PE=0表示CPU工作在实地址方式,PE=1表示CPU工作在虚地址保护方式。
80386/486的存储器管理机制采用了分段和分页管理。
分段机制是先把逻辑地址转换成线性地址,然后用分页机制把线性地址转换为物理地址。
(段的二维地址通过段表转换为线线性地址,再通过页表转换为物理地址。这就是我们MMU做的事)
逻辑地址都由一个段地址和偏移量组成,是在程序中对存储器地址的一种表示方法,逻辑地址 = 段地址:偏移地址。当分页机制被禁止使用时,线性地址就成了物理地址了。
(1)段选择符和段寄存器
段寄存器用来存放段选择符,段寄存器有CS、DS、SS、ES、FS、GS,段选择符是16位,而偏移量位一个32位长的字段。
段选择符是由16 位组成的,这16 位又被进一步分成3个部分,分别是:13 位索引字段、1 位的指示符字段TI 以及2 位的请求特权级字段RPL。
段选择符 | ||
---|---|---|
13 位索引字段 | 1 位的指示符字段TI | 2 位的请求特权级字段RPL |
- 索引指端指定了放在GDT或LDT中相应的段描述符的入口。
- TI标志知名段描述符是在GDT(TI=0)还是在LDT(TI=1)中。
- RPL表示当前的段选择符装入到CS寄存器时指示出CPU当前的特权级。
(2)段描述符
每个段由一个64位(8字节)的段描述符来表示,它描述了段的特征。
段描述符存放在**全局描述符表(GDT)或局部描述符表(LDT)**中(这两个就是我们的段表,有全局段表,局部段表)。
由于每个段描述符为8个字节,所以段描述符在GDT或LDT内的相对地址为段选择符的最高13位的值(也就是段选择符的索引字段)乘以8。
段描述符中各个字段和标志的含义如下:
- 1)基地址字段Base(Base address field):包含段的首字节的线性地址。
- 2)段限长字段Limit(Segment limit field):用于指定段的长度。如果G=0,则段长度Limit范围可从1字节到1MB之间,单位为字节;如果G=1,则段长度Limit范围可从4KB~4GB,单位为4KB。
- 3)粒度标志G:如果该位为0,则段的单位为字节;如果位为1,则段的单位为4KB。可以结合段限长字段Limit来理解。
- 4)段类型字段TYPE(Type field):描述了段的类型特征和它的存取权限。该字段的解释依赖于描述符类型标志S,由S来解释是一个代码或数据段描述符,还是一个系统描述符。TYPE字段的编码对代码、数据或系统描述符都不同。
- 5)描述符类型标志S(Descriptor type flag):如果S=0,则一个段描述符是系统段描述符,比如存放LDT这种关键的数据结构;如果S=1,则存放代码或数据段描述符。
- 6)描述符特权级字段DPL(Descriptor privilege level):描述符的特权级,用于控制对段的访问,表示CPU访问这个段需要的最小的优先级。特权级范围从0到3。0级特权级最高,3级最低。
- 7)段存在标志P(Segment present):用于指出一个**段是在内存中(P=1)还是不在内存中(P=0)。**对于linux是来说总是把这个标志设为1,因为它从来不把整个段交换到磁盘上去。
- 8)D/B(默认操作大小/默认栈指针大小和/或上界限)标志(Default operation size/default stack pointer size and/or upper bound):根据段描述符描述的是一个可执行代码段、下扩数据段还是一个堆栈段。这个标志具有不同的功能,对于32位代码和数据段,这个标志应该总是设置为1;对于16位代码和数据段,这个标志被设置为0。
- 9)可用和保留位(Available and reserved bits):由操作系统使用,但是linux忽略该字段。
(3)段描述表及段描述表寄存器
80386/486 微处理器有全局描述符表寄存器GDTR、局部描述符表寄存器LDTR 和中断描述符表寄存器IDTR,通过它们分别来查找全局描述符表GDT、局部描述符表LDT 和中断描述符表IDT。
(存放段表首指针)
(4)分段和分页机制
分段单元把逻辑地址转换成线性地址。
由于段选择符的高14位(13位索引号和1位TI位)是用来进行段描述符选择的,因此虚拟存储器中的段数最大可到16K(2的14次方)个;
TI位为1时,访问的是局部地址空间。通常在定义一个GDT,所有任务共享全局地址空间,如果每个进程除了在GDT中存放段外,还需要创建附加的段,则可以创建LDT,独立占有局部地址空间。
GDT在内存中的地址和大小存放在gdtr
控制寄存器中,当前正在被使用的LDT地址和大小放在ldtr
控制寄存器中。
一个逻辑地址如何转换成相应的线性地址。分段单元执行了以下操作:
- 1)检查段选择符中的TI字段,以此决定段描述符保存在哪一个描述符表中(GDT还是LDT中)。
- 2)段选择符的索引字段乘以8,**计算段描述符在描述符表(GDT 或者 LDT,由上一步决定)中的相对地址。**描述符表的首地址保存在
gdtr
控制寄存器或者ldtr
控制寄存器中(保存在哪一个寄存器中由上一步决定)。 - 3)段描述中的base字段的值就是段基地址,加上逻辑地址,就得到了线性地址。
分页单元把线性地址转换成物理地址。
在虚地址保护方式下(即控制寄存器CR0 的PE 位为1),控制寄存器CR0 中的最高位PG来决定是否启动分页机制,当PG=1,分页机制有效,可以把线性地址转换为物理地址;
当PG=0,分页机制无效,线性地址就直接作为物理地址使用了。
32位的线性地址被分成3个部分:最高10位为页目录索引,中间10位页表索引,最低12位偏移量。
线性地址的转换分为两步,都基于转换表,第一步的转换表称为页目录表(page directory),第二步的转换表成为页表(page table)。
也就是这里使用的是两级页表机制
复习一下页表机制:
- 线性地址被分为以固定长度为单位的组,称为页(page);分页单元把所有的RAM分成固定的长度的组,称为页框(page frame)。
- 每个页框与页打的长度一致,一个页框包含一个页。页框是存储器中的一部分;而页是一个逻辑上的概念,它既指一组线性地址,也指包含在这组地址中的数据,页包含的数据既可以在存储器中,也可以在磁盘中。
一个线性地址如何转换成相应的物理地址。分页单元执行了以下操作:
- 1)页目录基地址寄存器CR3提供页目录的页框地址(即页目录基地址),以页目录基地址为开始,加上线性地址中的页目录索引的值,就在页目录表中找到页目录项,从页目录项中可可以得到页表的基地址值(它的低12位为0)。
- 2)以页表的基地址值开始,加上线性地址中的页表索引的值,得到页框的物理地址(也就是页框的首物理地址)。页框的物理地址加上线性地址的偏移量,就得到了线性地址在页框内的物理地址。
从80386开始,Intel微处理器的分页单元处理的4KB的页,每一页的起始地址总是在低12位为0的线性地址上。分页管理把线性地址空间中的任何一页映射到物理空间的一页。采用分页管理机制实现线性地址到物理地址转换映射的主要目的是便于实现虚拟存储器。采用二级页表的目的在于减少每个进程页表所需的RAM数量。如果只使用一级页表,那么有2的20次方个表项来表示每个进程的页表,一个表项4个字节则需要4MB RAM来表示所有的页表项。
在两级页表中,有页目录表项和页表项,它们有相同格式。(就是两级页表咧,可以适度复习一下)
- 页框地址:一个页的起始地址称作页框地址。由于一页的大小为4KB,所以在一个页表项内,高20 位就是用来说明一个页框地址的,而低端12 位是用来说明页的控制和状态的。在一级页目录内,页框地址就是指向对应页表起始地址;在二级页表内,页框地址则是指向存储器中页的起始地址。
- 存在位P:P=1,表示所指的页(页表项)在物理存储器内;P=0,表示所指的页(页表项)不在物理存储器内。在执行一个线性地址转换所需的页表项或是页目录项的P为0,那么分页单元就把该线性地址存放在控制寄存器CR2中,并产生14号异常:缺页异常。
- 读/写位R/W:R/W=1 写,否则为读。用来表示对页(页表)的存取权限,它与地址转换无关。
- 用户/监控程序位U/S:用来表示访问页(页表)所需的特权级。
- 访问位A:用来表明该项指出的页是否已被读或写。若目录项中A=1,则表示该项所指出的页表已被访问过;若页表项中A=0,则表示该页表项所指出存储器中的页未被访问过。分页单元从来不重置这个标志,而是必须由操作系统做。
- 脏位D:只用于页表项中。每当对一个页框进行写操作时就设置这个标志。
- 可用域AVL:该域共3 位,供系统软件设计人员使用。可将与页使用有关的信息放在该域中,帮助分析判断应把哪些页移出存储器。
- PWT 和PCD:控制硬件高速缓存处理页(页表)的方式。
参考一下请求页表:
页号 | 内存块号 | 状态位 | 访问字段 | 修改位 | 外存地址 |
---|---|---|---|---|---|
old | old | new | new | new | new |
这个由页表的连续来隐式存储的(实际上也是利用了连续空间的随机存储特性,映射快速访问) | 页在内存中的基址 | 1位,是否调入内存 | 记录最近访问了几次或者是上次访问的时间,用于置换算法 | 页面调入内存后是否被修改过 | 页面在外存中位置 |
对比一下
页框地址 | 存在位P | 读/写位R/W | 用户/监控程序位U/S | 访问位A | 脏位D | 可用域AVL | PWT 和PCD |
---|---|---|---|---|---|---|---|
物理地址 | 状态位 | 保护机制 | 保护机制 | 修改位 |
(5)转换后援缓冲器TLB
(也就是这里实现了快表机制)
从上面线性地址的转换过程可以看出进行一次地址转换需要访问两次内存:一次访问页目录表,一次访问页表。
为了加速地址转换过程,80386在芯片内部设置了一个称为转换后援缓冲器TLB(Translation Lookside Buffer
)的部件。
TLB的每项存放着32个线性地址值((线性地址的高20位,即页的基地址)和对应的物理地址值(物理地址的高20位,即页框的基地址),另外还包含页的访问权等属性。
当线性地址在转换时,将线性地址的高20位与TLB中的线性地址的值比较。
- 如果找不到,通过上面的转换方式计算出对应的物理地址,同时该物理地址被存在一个TLB的表项中;(未命中,替换,使用全替换策略)
- 如果能找到则可以得到页框的基地址,加上线性地址的低12位即可得到物理地址。(命中)
由于TLB具有32项,能表示出当前常用的32个页与页框的对应关系,而每页为4KB,因此TLB实际上表示出128K个((32*4KB=128KB))线性地址和物理地址的对应关系。
由于程序和数据具有局限性,而TLB中可容纳128K个地址的转换信息,利用TLB进行地址转换有极高的命中率,一般可达98%左右。
当CPU的控制寄存器CR3的值被修改时,硬件自动使得TLB的所有的项都无效,因为新的一组页表开始使用了。这样以后对同一个线性地址的转化可以快速得到。
3.虚拟8086方式
它与实地址方式相比就多了一个可选的分页功能。在该模式下,由段寄存器中的基地址左移动4位后于偏移地址,结果为线性地址。如果启动了分页功能,则要使用分页机制将其转换为物理地址,没有启用则线性地址就是物理地址。
三、Intel 80386 的保护机制
1.段级别保护
(1)不同任务之间的保护
为了保护不同任务,通过将每个任务放置在不同的虚拟地址空间来实现。
每个任务中进行定义虚拟地址到物理地址的映射函数,随着任务切换后映射函数也会随着切换。
由于每个任务各有一组独立的映射表,即具有不同的地址转换函数,当处理器进行切换并执行新的任务时,为新任务切换任务的转换表是重要的一部分。对于不同的任务,它们可以有相同的虚拟地址,由于有各个的映射函数,所以不同的任务的物理地址是不同的。
(2)同一任务内的保护
同一任务内的保护机制更适合于保护操作系统,使操作系统由所有任务共享,并且可在每一任务中对其进行访问不被应用程序破坏。
各个任务都可以共享使用的虚拟地址空间,称为全局地址空间;
仅由一个任务使用虚拟地址空间,即不被任何其它任务共享的虚拟地址部分,称为局部地址空间。
操作系统在虚拟地址空间的划出一个公共区域,每个任务都可以使用该虚拟地址空间并映射到相同的物理地址上。
在虚地址保护方式下80386/486 微处理器的段级别保护分为4 级保护。每个任务是分离的,其中:
- 特权级0 是最高可靠性的特权级;
- 特权级3 是最低可靠性的特权级。
每一特权级都有各自独立的程序堆栈,以避免与共享栈区有关的保护问题。
当一个程序从一个特权级切换到另一个特权级执行时,程序使用的堆栈从原特权级的栈段改变为新特权级的栈段。堆栈段寄存器 SS来说,描述符特权级(DPL)必须等于当前代码段的特权级(CPL)。
每个存储器段都与一个特权级别相联系,程序只有拥有足够的特权级别才能对相应的段进行访问。特权级别用数字0、1、2和3表示,数字较大的级别具有较低的特权。在比较特权级别时,使用“里面”或“内层”这样的术语表示较高特权级使用“外面”或“外层”这样的术语表示较低特权级别。
- 在特权级0 中,通常配置操作系统内核,主要包括任务和内存管理,任务和I/O 设备间的通信等。
- 在特权级1 中,不属于内核的系统标准服务的程序,比如文件共享、数据通信等。
- 在特权级2 中,通常配置对操作系统进行扩充的用户化的程序,这些是依赖于内核的服务,例如,数据库管理程序或逻辑文件访问系统等。
- 特权级3 分给用户应用程序,在该级别上应用程序之间及它们与操作系统之间都应该互相隔离,互不影响。
- 4 级特权级不是都必须使用的,由操作系统自己决定。
2.页保护机制
Intel 80386提供页级保护。分页机制**只区分两种特权级,特权级0、1和2统称为系统特权级,特权级3称为用户特权级。**在页目录表项和页表项中的保护属性位R/W和U/S用于对页进行保护。
- (1)**R/W位表示该表项所指定的页是否可读、写或执行。**R/W位对页的写保护只在处理器处于用户特权级时才起作用;如果处理器处于系统特权级时,R/W位被忽略,即总可以读、写或执行。若R/W=1,对表项所指定的页可进行读、写或执行;若R/W=0,对表项所指定的页可读或执行,但不能对该指定的页写入。
- (2)U/S位表示用户/系统属性位,用来表示访问页(页表)所需的特权级。若U/S=1,表项所指定的页是用户级页,可由任何特权级下执行的程序访问;如果U/S=0,表项所指定的页是系统级页,只能由系统特权级下执行的程序访问。
线性地址转换为物理地址的过程中会进行页级保护的检查是,如果违反页保护属性的规定而对页进行访问(读/写/执行),则会引起页异常。