看完了linux书第二章后,关于内存寻址的一点总结

自己的总结,也就是自己的一些理解,纯手打,会出错,当然我自己理解的有些可能就是错的,这里只是暂时的记一下,

如果以后发现什么错误的话,再回来改下。



这里说的是80x86系列的CPU。


几个概念:

段是什么:程序猿在开发程序的时候,不会注意真实的电脑的内存是多大,他只是开发自己的,哪怕最后开发出来的

东西会占用10G的内存,他都不管,也真是任性(也不是真的不管)。为什么会不管这个,因为操作系统的设计者,给程序

猿提供了另一份内存空间,而程序猿看到的这个内存空间就是虚拟地址空间,这个空间里面,使用虚拟地址来标记的,怎么

标记的,就是用---------> 段 :偏移量  <--------------来标记的。所以说这个段,就是虚拟地址的基本单位。注意,注意:最开

始的时候,这个段就是虚拟地址中段的基地址,但是后来存放段基地址的寄存器不给力,于是就不再在里面存放段基地址了,

所以这里的段表示的虽然是段的基地址,但是真正的东西应该是一个  -----------> 段选择符 :偏移量<-----------,根据这个段

选择符,就可以查到段基地址,嗯嗯,就是这样的。


段描述符表是什么:虽然说段是虚拟地址空间的虚拟地址的基本单位,但是仅仅根据一个--------> 段 :偏移量  <-----------

是无法确定段的信息的,所以说这里就需要一个东西来描述段的所有必须的信息,这个东西很重要重要重要,叫做:段描述符。

跟上面的段选择符千万不要混淆,这个段描述符很多,把很多个段描述符放在一起就变成了一个表,这个表呢,就是段描述符

表。所以说,段描述符表是什么,就是一大堆描述段信息的段描述符放在一起。

注意,一个段描述符是8个字节,8乘8是64,也就是用64位的信息来描述一个段的信息,而这64位信息里面包含什么呢 ,

它包含了段的32位基地址(很重要,看到没,真正的段基地址是保存在段描述符中的,而最上面的那个段选择符,就能找到这

个基地址),20为的段界限(也就是这个段的长度),还有其它的一些很繁琐的东西,我不说了。


首先,得知道几个寄存器:

1、8个通用寄存器,名字不重要,记住这8个寄存器是32位的。

2、4个段寄存器,记住这四个家伙是16位的,在32位的CPU结构中,这几个寄存器里面根本存不下段的地址,所以

这四个家伙里面存了一个叫做段选择符的东西,当然 ,这个段选择符就是16位的,后面会提到这个段选择符,这四个段

寄存器分别是CS,DS,SS,ES。分别存放着代码段,数据段,堆栈段,其他段的段选择符。

3、4个控制寄存器,都是32位的,这四兄弟的名字很好记,叫做CR0,CR1,CR2,CR3。其中,CR1是个无用的

家伙,它里面全是0 。注意其他三个控制寄存器,其他三个里面比较重要的是CR0和CR3。


然后说一个很厉害硬件电路,叫做MMU(内存管理单元),CPU大人就是把虚拟的地址给这位硬件,然后让它去处理。

MMU从外面看是一个东西,但是里面包含了两个部件,一个是分段部件,一个是分页部件。也可以叫做分段机制,和分页机

制。


知道了上面这个东西后,有一个图很重要,如下。

看完了linux书第二章后,关于内存寻址的一点总结_第1张图片

图的解释:这个图就是MMU把虚拟地址进行处理最终转换为物理地址的过程。

其中,注意最开始的16位的选择符,这个东西就是存在那4个16位段寄存器中的东西;而后面的偏移量就是存在那8个32位通用寄存器

中的东西。这两个东西通过MMU中的分段部件,也就是分段机制,被处理成线性地址,然后线性地址再被MMU中的分页部件,也就是分页

机制处理成内存中真实的物理地址。


了解了上面的内容后,就可以说说整个处理的流程了。

1、首先呢,我们将上图中的选择符装入那四个16段寄存器的某一个中。

2、然后将后面的32位的段偏移量装入那8个32位的通用寄存器的某一个中。

3、然后MMU中的分段部件,就开始对这两个东西进行处理了。

4、怎么处理,就是检查选择符中的内容来处理。首先选择符中有个索引域(13位),根据这个域的信息就可以找到一个很重要的东西,这个东西就是

段描述符,注意,上面说过了,段描述符在段描述符表里面。而这个索引域的信息就跟段描述符表中的索引对应,所以能找到相应的段描述符。

5、找到这个段描述符后,因为这里面几乎存了段的所有信息,当然就有32位的段基地址了,知道32位的段基地址后,就万事大吉了。

6、在第四步和第五步还会检查一些标志位,如果这些标志位都正常的话,就会来到第六步,这在里把刚才拿到的段基地址跟第二步里面的段

偏移量相加,就得到了一个新的地址,这个地址就是传说中的线性地址(说实话,以我现在理解的水平,并不知道这个线性地址为什么会存在在

这个世界上)。

7、然后呢,看上面的图片,线性地址将会被送到MMU的分页部件加工厂,来处理成物理地址。


再说后半个线性地址转换为物理地址之前,需要理几个概念:

什么是页:为了提高计算机的处理效率,一切都是为了效率,所以把线性地址空间划分为了一些个大小相等的片,这个片,就是所谓的页。

这里可以稍微想一下,我们平时看的书,一页一页的,而且每页都有自己的编号,每页的大小都是一样的,在x86中,把这个页的大小规定为

4KB。而对应的,也把物理地址空间划分为大小相等的存储块,成为块或者叫做页面(晕,好烦)。

那么是什么是页表:页表就是,就是,想一下段描述符表,就知道了,页表里面放的是页的一些信息,根据这个信息就能查到这个页了。

这些信息是什么信息呢,就是页的基地址和一些属性啦。这里有个很重要的概念必须说,那就是,你想,因为每一个页都是4KB大小,那么在

4GB的线性地址空间里面就有    2的20次方    个页了(也就是1M个)。那么对于一个32位的系统来说,要用2进制从0表示到2的20次方减1,

需要多少位,当然是20位啦啦啦,然后还剩下12位来表示什么,你想想,用20位表示完了每一个页的基地址,然后还有12位来表示的当然

是页的属性啊。所以说一个页表里面的页表项刚刚好,刚刚好就可以用4B(32位)的空间来描述一个页了。而用一个页面来存一个页表的话,

那么这个页表就包含了4KB除以4B等于1K个页表项了。(这里并不是很好理解,多读几遍就好了,不行就在纸上画一下就明白了。)

然而,一个页表里面的一项的大小是4B(32位),那么上面说了一共有1M个页表,那么就需要    4乘2的20次方B     的空间来存这些个

页表。啊啊啊啊,这个就需要浪费掉4MB的空间,而且每次查找什么的,都会浪费很多时间,这样就是既浪费了空间,也浪费了很多时间。

要你何用。

因为从上面看页表的作用并不是很大,但是那只是一级啊,虽然一级的页表看似无用,但是如果用两级,或者三级呢。此处,请想一想

书的目录,是不是有二级目录和三级目录呢,所以呢,将上面那4MB大小的页表再按照一个页面4KB的分法,分出来,结果呢 ,就分出来了

4MB除以4KB等于1K个页。而上面说过,描述一个页面刚好32位(4B)空间就够了,所以1K个页面就需要4KB的空间。啊啊啊啊啊,简直了

,刚刚好刚刚好又等于4KB,刚好是一个页面。这样就形成了两级页表。

注意,注意,这里又有个很重要的东西,那就是这1K个页表,在32位系统中表示的话,用二进制数只需要10位就可以把它们从0数到

1024了。首先呢,根据这10位就可以找到一级页表的具体某一个页表项了,然后根据这个页表项就能找到具体的页表,而一个页表呢 ,又

包含了1K个页表项,那么又需要10位来表示这1K个页表项了。而对于一个页面来说是4KB,总不能根据前面的20位定位到了这个页面,然后

需要从这个4KB大小的页面里面来寻找需要的地址吧,所以我们需要一个页内偏移量,想一下,要用2进制从1数到4K需要多少位,当然是

12位啦啦啦啦。你看,巧不巧,刚好,10+10+12就是32位了,这32位就能定位到一个具体的地址了。


想一想,想一想,前面什么是32位的,当然就是我们刚才得到的线性地址啊,所以呢,就用这个线性地址的32位就可以在线性地址空间

里面具体定位出来一个地址了。


那么接下来就继续谈谈,线性地址是如何转换为物理地址的。

8、在第六步得到了一个32位的线性地址,首先将这个32位的线性地址的高10位取出来,这个高十位就是一级页表的页表项,取出来后,

因为这个只是在一级页表中位置,并不是真实的位置,我们需要从最开始介绍的那4个控制寄存器中找到R3,取R3的高20位,这个高20位就

表示的是页目录(一级页表)的基址,可是这拼接在一起才30位,还差两位呢,所以需要把线性地址的高10位左移两位,也就是乘以4。

9、在第八步中形成了32位的一个地址,这个地址是什么呢,就是一级页表在内存中的位置,然后我们根据这个地址就能找到对应的一级

页表中的某一个项了。

10、找到这个项后,因为每个项都是32位(4B)大小,所以读取4B的内容,因为一共有4M个2级目录,所以需要读取这32位的高20位,

这高20位上面也说了就是对应的二级页表的地址,而一个二级页表里面还有1K个页表项呢,这个就需要我们最开始得到的那个线性地址的中间

十位来表示了(这中间十位就是除了高10位后的紧接着那10位),和第九步一样,需要将这10位左移2位,和刚才得到的20位拼接成32位的

地址,这个地址就是二级页表在内存中的地址了。

11、然后呢,我们根据这个地址就可以在内存中找到二级页表的具体某一项了,而就可以根据这一项(32位)得到我们最终要查找的那个页

的地址了,怎么得到呢。因为我们之前一共有1M个页面,所以需要20位来表示具体是哪个页,而二级页表的项的高20位就是让我们来找到这个页

的,找到具体的这个页后,这个页是4KB大小,为了表示这4KB大小的空间,需要12位的2进制数,也就是我们线性地址的最后剩下的低12位,

把刚才得到的高20位和这个低12位拼接起来就是最终最终最终的32位物理地址了。


至此,我简单的说了一下内存寻址的过程,虽然是简单说了一下 ,但是还是用掉了我很多的时间,fuck。



你可能感兴趣的:(看完了linux书第二章后,关于内存寻址的一点总结)