------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
以下为自己的总结的x86保护模式知识
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
x86虚拟地址空间64TB,通过分段/分页映射到物理内存。而linux 实际上只是有限的使用了分段机制(比如使用了段的特权级保护),并没有利用分段机制实现虚拟化,所以linux下每个进程的虚拟空间,或者说编程空间只有4GB,而不是64TB。 假设现在我们要利用x86的分段机制实现虚拟化,将虚拟空间变成64TB,那么与分页机制实现的虚拟化相比,有什么不同的地方呢?讨论如下:
在分页机制下,每个页大小为4KB,对于x86来说,一个页表项一旦建立,4KB的物理内存就已经被 “ 使用 ”了,即使实际上你只使用了一个字节。。因此,系统内能同时存在的页表项的个数x4KB,不能大于实际物理内存,其余的页表项必须标识为不存在。那么在分段机制上,段的大小是不固定的,但是一旦在段描述符中确定大小后(假设为N个字节),与分页机制一样,即使你只用了一个字节,对x86来说,N个字节已经被 “ 使用 ”了。。因此,系统内能同时存在的段的个数是不固定的,但他们的大小之和不能大于系统物理内存。
x86有32位地址线,对于linux来说 由于没有利用分段机制实现虚拟化,虚拟地址的选择子都是操作系统填的,程序员只需要关注偏移地址,不管选择子是多少,段描述符中基地址都为0,也就是虚拟地址统一映射到偏移地址,这样一来,16位选择子不参与地址映射了,16+32位地址等于变成了32位地址,64TB虚拟空间被压缩到了4GB线性空间(也就是说linux下虚拟地址的偏移部分等于线性地址),再由分页对这4GB空间进行虚拟化。。 假设我们要让16位地址参与映射,实现64TB虚拟空间,就要注意线性地址不能 “ 冲突
” (在linux中,实际上线性地址是“ 冲突 ” 的,比如选择子为1,偏移为0xffff,和选择子为2,偏移为0xffff,都映射到一个线性地址0xffff),具体来说就是 线性地址由选择子和偏移地址共同唯一确定,但毕竟只有32位地址线,映射完4GB线性地址后,多出来的64TB-4GB的虚拟地址如何表示呢,答案是无法表示,那么会有问题吗,不会!因为这部分地址所在段的存在位是0。分页机制总的虚拟空间只有4GB,正好够32位数来表示,所以整个虚拟空间都能用线性地址表示出来,而在分段机制中,大于4GB的虚拟地址无法表示,但反正也不存在,所以对虚拟化实现没有影响,要用时,释放掉之前使用的一些线性地址,把大于4GB的那些虚拟地址映射过去就行了,总之,64TB虚拟空间中,能表示为线性地址的就4GB,其余的就无法表示且存在位为0。
到此为止。