os读书笔记2
保护模式内存管理
2.1. 内存管理概览
有三种地址
-
逻辑地址
-
线性地址
-
物理地址
逻辑地址由一个16位的段选择符和一个32位的偏移量offset组成,对CPU来说每一个操作都是由逻辑地址来协助完成的。
通过段选择符,找到目标段,再加上偏移量找到线性地址,线性地址即程序运行时候的虚拟地址。
线性地址的一些标志位会记录这些页的权限。
最后线性地址分为三部分Dir、Table、Offset三个部分分别用于查找Page Directionary、Page Table,最后结合offset可以找到具体的物理地址。
通过三个地址,实现了由CPU到物理地址的访问流程,中间经历了许多表,这些操作都是为了扩大访问范围,以少量的总线访问大量的存储空间。
2.2.分段机制
Basic Flat Model
这个模型是最直白的模型,也就是没有经历我们上述的分段、分页的转换等流程,CPU直接访问的就是物理内存,一对一映射。
在这个模型中我们仍需要建立至少两个段描述符,代码段和数据段,并且两个段都要映射进内存空间。
Protected Flat Model
这个模型下,段长被限制在一定范围内,不允许出现越界访问等问题。
它将代码段/数据段/堆栈段等写在特定的地方,不允许例如代码段的段描述符访问到数据段这种情况,对内存进行了隔离和保护,是一种内存管理和保护的理论模型,通过划分地址空间为多个区域并设置不同的访问权限,实现进程间的内存隔离和保护。
但是不同程序之间能够相互访问数据,不存在互锁的情况。
Multi-Segment Model
这个模型下,充分利用了分段机制,提供了对代码、数据、堆栈的一种更高级的保护,每个进程都拥有独自分配到的段,也可以与别的进程共享这些段。防止了不同程序之间越界访问。
2.3. 逻辑地址和线性地址的转换
段选择子结构
段选择子长度为16bits,其低位3bits是标志位
RPL标志位占2bits,表示请求段的特权级
这里的特权级就是Ring0-Ring3,也就是内核态特权和用户态特权,越权访问会被禁止
TI标志位表示要给到的表是GDT还是LDT
Index是表中的下标,可以访问8192个,但是GDT的第0位是置空的,所以在GDT只能访问8191个段描述符。
段寄存器
处理器提供了6个段寄存器,代码寄存器(CS),数据段寄存器(DS),堆栈段寄存器(SS),以及另外三个数据段寄存器(ES、FS和GS)给进程使用。
每个段寄存器都由两部分组成,一部分是程序员可见,另外一部分是不可见的。
不可见部分包括了段基址、段限长和访问权限。
载入段寄存器一般有两种指令:
-
直接载入指令,如:MOV,POP,LDS,LES,LSS,LGS和LFS,这些指令明确指定了相应的寄存器。
-
隐含的载入指令,比如CALL,JMP,RET等指令,伴随着这些指令,改变了CS寄存器的内容,有时候也会改变别的寄存器的内容。
段描述子
结构如图。
段基址
指向段在内存中的起始地址。处理器会将三个基地址组合在一起构成一个32位的地址。
类型域
指明段/门的类型,会设定访问权限、或者门/段的各种特点。
S(描述符类型)标志
确定段描述符是系统描述符(S标记为0)或者代码、数据段描述符(S标记为1)
DPL(描述符特权级)域
指明该段的特权级。特权级从0~3,0为最高特权级。
P(段存在)标志
标志指出该段当前是否在内存中(1表示在内存中,0表示不在)。当指向该段描述符的段选择符装载人段寄存器时,如果这个标志为0,处理器会产生一个段不存在异常(NP)。
D/B(默认操作数大小/默认栈指针大小和/或上限)标志
根据这个段描述符所指的是一个可执行代码段,一个向下扩展的数据段还是一个堆栈段,这个标志完成不同的功能。(对32位的代码和数据段,这个标志总是被置为1,而
16位的代码和数据段,这个标志总是被置为0)
G(粒度)标志
确定段限长扩展的增量。当G标志为0,段限长以字节为单位;G标志为1,段限长以4KB
为单位。(这个标志不影响段基址的粒度,段基址的粒度永远是字节)如果G标志为1,那么当检测偏移量是否超越段限长时,不用测试偏移量的低12位。
将逻辑地址转换成线性地址的,处理器:
-
分段:处理器通过段选择子和段描述符将逻辑地址中的段部分与段基址相对应起来。段基址表示段的起始地址,段选择子包含了段的索引和特权级等信息。
-
分页:在分段的基础上,处理器使用页表将逻辑地址中的页部分转换成物理地址的页表项索引,并获取对应的页表项。
-
偏移计算:根据逻辑地址中的段内偏移部分和获取的页表项中的页框基址,通过加法运算得出线性地址的偏移部分。
-
线性地址生成:将分段的段基址与偏移计算得到的线性地址偏移部分相加,即可得到线性地址。
2.4. 描述符的分类
代码段/数据段描述符:
当段描述符中的S标志(描述符类型)为1时,该描述符为代码段描述符或者数据段描述符。类型域的最高位(段描述符的第二个双字的第11位)将决定该描述符为数据段描述符(为0)或者代码段描述符(为1)。对于数据段而言,描述符的类型域的低3位(位8,9,10)被解释为访问控制(A),是否可写(W),扩展方向(E)。参考表3-1对代码和数据段描述符类型域的解码描述。数据段可以是只读或者可读写的段,这取决与“是否可写”标志。
系统描述符:
系统描述符分为:
-
局部描述符表(LDT)段描述符
-
任务状态段(TSS)描述符
-
调用门描述符
-
中断门描述符
-
陷阱门描述
-
任务门描述符
这些描述符又可以分为两类:系统段描述符和门描述符。系统段描述符指向系统段(LDT
和TSS段)。门描述符它们自身就是“门“,它们或者持有指向在代码段的过程的入口点
的指针,或者持有TSS(任务门)的段选择符。