1中讲述了分段机制,那么LUNIX中的段是什么样子的?
由于大多数硬件都不支持段机制只支持页机制,为了使LINUX具有更好的可移植性需要去掉段机制而只使用页机制。80x86规定段机制是不可禁止的。因此不能绕过他而只给出线性地址。聪明的LINUX设计人员让段基地址为0,段界限为4GB,这样虚拟地址和线性地址就是同一个。80X86规定必须为代码段和数据段创建不同的段所以LINUX必须为代码段和数据段分别创建一个基地址为0段界限为4GB的段描述符。LINUX内核运行在特权级0用户程序运行在特权级3,80x86规定特权级为3的程序无法访问特权级为0的段。LINUX必须创建四个段描述符-特权级为0的代码段和数据段,特权级为3的代码段和数据段。
LINUX内核不区分数据段和堆栈段,体现了LINUX尽力少使用段。
LINUX这样进行段机制基地址全是0这样可能多个段使用相同的线性地址空间,会相互覆盖。就需要使用分页机制
分页机制
把线性地址转换为物理地址
1.用32位线性地址最高10位作为页目录项的索引,将它乘以4与CR3中页目录的起始地址相加,获得相应目录项在内存的地址
2.从这个地址开始读取32位页目录项,取出其高20位,再给低12位补0,形成的32位就是页表在内存的起始地址
3.用32位线性地址中的中间10位作为页表中页表项的索引,将它乘以4与页表的起始地址相加,获得相应页表项在内存中的地址
4.从这个地址开始读取32位页表项,取出其高20位,再将线性地址的第11-0位放在低12位,形成最终的32位页面的物理地址
页:线性地址空间分成若干大小相等的页。
页面:物理地址空间划分成与页大小相等的若干存储快。
页过大过小都会影响内存的使用率。确定4KB是最好的
页表:把线性地址映射为物理地址的一种数据结构,与段表类似。包含两部分(1)物理页面基地址:线性地址空间的一个页装入内存后所对应的物理页面的起始地址。(2)页的属性:表示页的特性,比如该页是否在内存中是否可被读出或者写入。
页面的大小为4KB他的物理页面的基地址肯定是4K的倍数,因此他的最低12为全为0(例如地址是100的倍数,则后两位全为0),可以用这12为来存放页的属性。这样32位地址就可以完全描述页的映射关系。
但是呢????????????????
线性地址空间为4GB,4GB/4KB = 1M,线性地址空间被划分为1M个页那么就有1M个页表项,每个页表项占4个字节。总需4M的连续空间,这当然是不可能的。
解决的办法是使用两级页表:
两级页表就是对页表再进行分页。4MB的页表再进行分页可以分为1K个页,每个页表项占4字节,总共4K大小正好一个页。也即是这4K的大小可以存放4GB的线性地址空间的所有映射信息。
线性地址总共32位,高10位是页目录,有10位表示页表目录项的下表,指向一个页表。中间10位是页,表示一个具体页表中目录项的下标。最后12位是offset表示物理页面中的偏移量。
页表的结构
不管是页目录还是页表,每个表项占四个字节,其表项结构基本相同。
物理页面基地址:对页目录而言,指的是页表所在物理页面的内存的起始地址。对页表而言是指页所对应的物理页面在内存的起始物理地址。
其他还有一些属性位,请大家参阅书籍这里不再详细说明。