Real Mode 8086
16位寄存器
20位地址
使用CS DS SS ED段寄存器
16位寄存器 << 4(基地址) + 16位地址
此乃实模式 Real Mode
Protect Mode 80386
保护模式实现思路
段式内存
GDTP (global descriptor table register) LDTR (local descriptor table 每个段寄存器在CPU上都有一个扩展, 当一个段寄存器被改变(MOV, POP)后,CPU会根据LDTP,GDTR+段寄存器的偏移,取出新的段描述符,放到这个寄存器的影子中。 因为GDTR,LDTR的操作是特权指令,只能在内核态中执行,用户看不到段描述符表在哪里,所以部分实现了保护。 最终的段值为 LDTR(GDTR) _+ 相应的段寄存器值的高13位
系统态和用户态(如何区分是系统态还是用户态呢?)
80386划分4个特权级别0是内核态,3是用户态 16位的段寄存器后3位,用来描述权限 typedef struct { unsigned short seg_idx:13; unsigned short ti:1; unsigned short tpl:2 /*Request Privilege Level 要求的优先级别*/ } 段寄存器;
页式内存
与段式之间的关系
建立在段式基础之上。当前执行的权限就是存在相关的代码段描述项中 逻辑地址 (段式)-> 线性地址 (页式) -> 物理地址 所有的地址都要经过页式的转换,包括GDTR, LDTR等
线性地址
typedef struct { unsigned int dir:10; unsigned int page:10; unsigned int offset:12; } ;
为什么要2级映射,而不是像段式那样一步倒位?
如果像段式一步倒位,前面20位可以提供1M的页面数的寻址。 那么,就必须开一个大小为1M的连续数组,用以定位页框下标。这个的设计,不需要页目录了大小是(4K),直接由1M大小的页表定位页面,然后,后面的12位的offset定位页内地址。 而采用2层,就可以,在需要目录项,页面表目录的时候动态的申请,而不是一次行的申请1M的连续的页表目录大小。类似于STL的deque数据结构。巧妙的设计。
页面4k,为什么?
上面说了,在需要目录项,页面表目录的时候动态的申请。 申请目录项:大小是1k,所占用的内存空间正好是4k,所以一个进程的页目录一个页面。 申请页表:一个页表大小也是10位,大小1k,内存空间是4k。 所以,申请目录项(一个进程一个),和页表项都是一个页面。 alpha CPU 64位cpu的页面8K。
目录项,页表项
目录项和页表项都是高10位起作用,低22用不到。这22用来控制权限,虚存等。
PSE
页目录项中的ps为0: 页面大小4k,采用2层; ps为1: 页面大小4M, 采用1层。