80x86保护模式中,地址分为逻辑地址,线性地址,物理地址?
逻辑地址即cs,ds,eip等,同8086?
80286以后引入了保护模式,可对内存块进行保护,所以除了地址本身,还必须有信息指出,受保护的内存块的大小?受没受保护等信息?如果还是用8086的模式来直接在cs,ds中放地址,那么32位的空间显然表达不了这些信息?所以这里的cs,ds中并不是放的物理地址信息,而真正的相关地址与其它信息存放在一个专门的数据结构中,叫做描述符,而逻辑地址中仅存放了描述符表中的索引号,按索引号去表中查找出相应的信息?一个cpu有一个全局的描述符表叫GDT,其地址存于寄存器gdtr中?每个描述符占8个字节,描述了相关的信息?如base,limit,取出其中的base加上eip的偏移量,得到线性地址?而cs,ds叫做段选择符,不像8086中叫段地址了?其中一个字段是刚才描述的索引,还有一个字段指出,指向的描述符在全局的GDT中,还是在局部的LDT中,最后有个字段是描述本段内存的优先级别CPL,用两位表示,一共有4种优先级,一般用0和3?现在地址叫线性地址,就是进程地址空间所用地址?
注意到,如果在描述符中将base字段置0,那么线性地址就等于偏移量了,因为有分页技术,linux没有过多使用分段,而仅仅将cs,ds按优先级不同分别存于GDT中,将base置0?以往8086中,线性地址就是物理地址了,保护模式下,分页单元支持分页机制,这就意味着从线性地址到物理地址还有另一层关系?
cpu分页单元将内存分成大小相等的页框,线性地址分为大小与页框相同的页,两者用一种叫页表的数据结构联系起来,为使存储量减小,可能使用多级页,第一级一般叫页目录,在页表项中,也有相应的项指定此内存块的保护级别,这里一般指出用户级和内核级2级?要注意的是,页表本身也是数据,它也得存在页框中,只是它由操作系统初始化?那么怎么去找页目录呢,它的物理地址存在cr3寄存器中,页表项还有一项present指出对应页框是否在主存,若不在,将线性地址存在cr2寄存器,产生14号异常,就是缺页异常?
硬件缓冲:每个cpu有sram实现的高速缓存,它们分为以行为单元的若干行,每行几十字节,与主存可以直接映射?N路关联?充分关联?它们由高速缓存控制器控制,后者维护了表项数组以便查找?页表项也有字段指出此页可否启用高速缓存?它的控制器写内存有回写和通写两种方式?一是仅写缓存,二是缓存内存同时写?为加快线性地址与物理地址的转换,cpu有TLB也是就快表来缓存页?
物理内存布局:PC体系结构决定:RAM第一个页框用于存放加电自检所得的硬件信息?0x000a0000到0x000fffff留给BIOS例程并映射图形显存,所以前1M物理内存是首尾被占用了一些的?而把linux内核装入连续的页框更好一些,所以跳过第一M,从第2M起存放内核代码段?数据段?bss段?此时,cpu仍在实模式下,接下来要开启分页机制?在bss段之后,存放两个页表,所以两个页表可映射到的物理内存为2X1024X4K=8M?这8M应该包括从0页框(自检的硬件信息)至2047页框,当前的所有内存数据(前1M?2M开始的linux内核?之后新加的2个页表)都应该在这个范围内?对于进程来说,地址空间从0xc0000000以上的1G都作内核用,所以这两个页表应该把线性地址0xc0000000开始的8M映射到物理内存的前8M,并将相关页表项中保护模式字段设为内核级?present置1等等?此时,可以将cr3寄存器指向页目录,将cr0的PG置位开启分页机制?具体linux启动过程在附录?