内存管理初探

来源:互联网 发布:飞鸽翻墙软件7.57 编辑:程序博客网 时间:2024/05/19 13:26

    Intel CPU的寻址从分段的实地址模式演变到了段式内存管理的保护模式又发展到了分页内存管理。在80386中,地址线达到32位与数据线相等,但是依然使用了段式结构。其变化在于,16位的段寄存器中保存的不再是单纯的基地址,而是一个数据结构, 第一部分是高13位,用来存放段描述表的一个索引,段描述表指全局段描述寄存器GDTR和局部段描述寄存器LDTR所指向的一个内存区域,这两个寄存器是后引入的,为的就是实现段式内存管理。段描述表里存放着段描述表项,而刚才提到的索引,就是指向一个描述表项的指针。也就是说,当我们开始寻址了,首先找到合适的段寄存器,然后,段寄存器->段描述表索引->段描述表项->段基址。在段寄存器中的第二部分是底3位TI,TI=0使用GDTR,=1使用LDTR。第三部分RPL,从00到11取值,说明了特权级别,00最高,11最低。由于段寄存器中的第一部分(索引)是13位,那么2^13=8192,也就是说明索引可以指向8192个不同的段描述表项。并且,每一个段描述表都是最大可达8192个段描述表项的。下面说段描述表项,每个表项是8个字节,也就是8*4=32位。因此可以计算出一个段描述表的最大的大小,8192(个表项)*8Byte(每个表项大小)=64KB。每个表项中包含了段基址、段长度值还有其他的一些信息。其中段基址是32位,段长度是20位。段基址好理解,那么为什么段长度是20位呢?2^20=1048576=1M,那么这1M并不是1M字节,而是1M个单位长度。在表项中有一位G,表示粒度,G=1时表示段的单位长度是4KB,G=0时表示段的单位长度是1字节,一般来讲G=1,也就是说段的单位长度是4KB,那么1M个4KB,1M*4KB=4G,而地址线是32位的,2^32=4G,所以正好是32位地址线寻址的范围。也就是说一个段最大长度是4G。

    当段寄存器的内容改变时,CPU就将段寄存器的新内容所决定的描述表项的装入一个高速缓存。这个高速缓存是用户不可见的。这个是段寄存器的扩展,因此,段寄存器中一部分对用户可见,一部分不可见。而不可见的部分是CPU内部使用。这是为了方便CPU重复访问一个段,而不用每次都去查询描述符表。

    Liunx内核使用的是FLAT地址,也就是说每个段寄存器都指向同一个段描述表项,而这个表项中的基址被设置为0,而段限被设成最大。这是一种段式内存管理的特殊应用,但是看上去就是逻辑地址与物理地址相同。

    页式管理是将段式映射出来的线性地址再进行一次映射,将地址分成3部分,31-22位是页面目录偏移地址,21-12是页面表偏移地址,11-0是页内偏移地址。当寻址时,先从CR3中取出页面目录的基地址,然后加上页面目录的偏移地址,找到页面目录中的一个目录项,这个目录项存放着一个页表的基地址,这个页面表基地址加上页表的偏移地址就找到了页面表中的一个表项,这个表项里存放着一个内存页面的基地址,这个基地址加上页内偏移地址就找到了内存中的实际物理地址。分页管理中每一个内存页面都是4KB。页面目录偏移地址是10位,也就是说一个目录中有2^10=1024个目录项,页面表偏移地址也是10位,也就是说一个页面表中可以有2^20=1024个页表项。这样看来页面表有1024个,而每个页面表中的表项又有1024个,那么表项一共就有1024*1024=1M个,而页内偏移地址是12位,也就是说一个页面的大小就是2^12=4KB,那么一个表项对应一个页面,所以总页面大小就是1M(个表项)*4KB(一个页面的大小)=4G空间,这就是32位地址总线的寻址空间。而要注意的是,一个页面表项或者一个目录项都是4Byte,因此,一个页面表的大小就是4B*1024(个表项)=4KB,正好存放在一个内存页面中。并且,页面表和内存页面的其实地址都是在4KB的边界上,也就是要4KB对齐,因此页面表和内存页面的基地址的低12位都是0,也就是说在目录表项和页面表项中,高20位是基地址,而低12位用来保存一些属性信息。

    分页中可以使用p位来进行虚存处理。这是在页目录项中,p=1说明页面在内存中,=0则说明在存储器中。而段式的段描述表项中也有p位,也是同样的意思,以可以实现虚存。

    问题:

    1、GDTR与LDTR是如何来确定的

    2、访问权限是如何来确定和应用的

    3、为什么段寄存器的扩展高速缓存在80386是64位的,一个段描述项是32位,为什么要用64位来存贮信息