内存管理之页表

页,帧和偏移量

Posted by Haiming on April 11, 2020

一个32位机器,如果采用一级页表,要使用4MB的内存来做页表。如何计算出这个结论的?

为什么32位的系统内存最大为4GB?

下面请看走近科学。

1. 虚拟内存和物理内存

在操作系统之中,进程是资源分配的最小单位。那么也就是说每一个进程都有独立的一块资源。这里的资源包括:

  1. 页表——对应虚拟内存资源
  2. 文件描述符表——对应打开的文件资源
  3. 寄存器——对应运行时数据
  4. 信号控制信息/进程运行信息

我们就来讲讲这里面的”页表“。

按照之前的描述,页表对应的是虚拟内存资源。那么什么是虚拟内存资源呢?存在的意义是什么呢?

对于程序而言,内存分配是必不可少的。但是如果直接让每个程序都对于物理内存直接操作,那么势必会有很多问题:比如冲突,占用等等。所以OS就将内存分配这件事做完了,对于每个进程而言,其所看到的都是OS给出的”虚拟空间“,在这个空间里面,不需要担心其他进程来修改自己的变量,不需要担心要抢夺资源的事情。那么OS如何去将”虚拟内存“和”物理内存“匹配上呢?这就需要页表了。

在Linux之中,将虚拟内存分成一个个的页(Page),其中每个页的大小是4KB。将物理内存分成一个个的”帧(Frame)”,大小和页的大小一样。然后OS会维护一个页表,这个页表之中记录的是页和帧的对应关系。

那么先来回答第二个问题。在内存之中,每一个位置都是一个Byte,8个bit。一级页表的意思是,所有的虚拟内存和物理内存都在这一张表之中匹配。那么为了对应到每一个内存单元,寄存器之中的命令是32位的,也就是:

4*2^10*2^10*2^10=4Gb的寻址空间,那么每一个寻址空间都可以对应一个内存之中的Byte,所以最大内存为4GB。

再来回答第一个问题:既然要所有的页表都在一个空间之中,那么可以得到:4GB/4KB=1M个对应的表项。

每一个页表项中都保存了很多东西,比如最基本的虚拟页号和物理页号、页偏移、页是否有效的有效位(比如表明是否已分配该页内存)、页是否可读/写/执行的保护位、页是存在于内存还是存在于交换分区的存在位、页是否修改过的脏位、页是否最近访问过的访问位,等等。

一般而言我们对一个页表项要分配4B的内存。那么综合起来,页表的总大小就是4MB。

刚刚我们还提到了一个概念,叫做页偏移。每一个页之中还有4KB的空间,那么如何标识数据在这个页内部的位置呢?这个页偏移就可以帮到我们了。

逻辑地址转换成物理地址的过程是:用页号p去检索页表,从页表中得到该页的物理块号,把它装入物理地址寄存器中。同时,将页内地址d直接送入物理地址寄存器的块内地址字段中。这样,物理地址寄存器中的内容就是由二者拼接成的实际访问内存的地址,从而完成了从逻辑地址到物理地址的转换。

不同进程的页表是不同的,因为其虚拟内存都是从头开始,那么为了避免混淆,一定要对每个进程有独立的页表。

2. TLB(translation lookaside buffer)

啥是TLB啊?听起来玄之又玄是不?就是普通的缓存概念而已。CPU的Memory management unit (MMU) cache了最近使用的页面映射,每次需要映射时候我先去这个TLB里面找找,如果找到了就直接返回对应的物理地址的操作,没找着就去内存接着找,然后采用一定的方式,比如LRU这种方式将TLB之中权重最低的一项替换掉。

3. 多级页表——Linux倾情代言

上面讲了,在页表项之中有个东西叫页是否有效的有效位(比如表明是否已分配该页内存),也就是说,页可以无效(没有对应的物理内存)。这很正常对不对,比如我待机状态只用了几百M的内存,你直接给我把8G全都分了,是不是没有必要?

那么这个时候多级页表的作用就体现出来了。先把参考链接放出来:https://www.cnblogs.com/f-ck-need-u/p/11783425.html

多级页表啥意思呢?就是我给你页表也分个表出来,叫页目录(page Director)。并且我在页目录之中记好了你这个页表是否有效。啥时候页表无效呢?当其对应的页全都无效——全都没有对应的物理内存的时候,页表就无效。如果某页表无效,就不为这段空间的页维护页表,这样就能减小页表的大小。这个逻辑其实很简单:对于没有分配的页,没有必要去记录这些页的翻译方式。

img

Like this。

这样子是不是就可以节省空间了?这就是多级页表,也是Linux之中正在使用的方式。