现代操作系统:内存管理(五)
Multilevel Page Tables多级页表
回想一下上面显示的数据段和堆栈段相互增长的图表。通常,堆栈包含在每个过程中定义的局部变量。它们在过程被调用时产生,在过程返回时消失。数据段包含了不具有如此容易定义的生存期的变量的空间。在C语言中,malloc()使用数据段,free()释放数据段。在Java中,空间由new使用,当变量不再可访问时,JVM会自动返回空间。
通常,大多数虚拟内存是数据和堆栈区域之间未使用的空间。然而,使用请求分页,该空间不会浪费实际内存。相反,它由没有加载到页框中的页面组成,实际上单页表确实浪费了实际内存。由于PTE是页面的0.1%,所以浪费的空间不是问题。最近,超大的虚拟地址空间已经成为可能,通常是1040GB或更多。如果其中大部分未使用,那么页表本身的大小为gb,这就浪费了实际内存。
多级页表的思想(类似的思想在Unix基于I/O的文件系统中使用,我们稍后在进行I/O时将对此进行研究)是添加一个间接层,并拥有一个包含指向页表指针的页表。
32位的地址空间,如果按照这样划分:一级页表包含1024个PTE,每个二级页表中包含1024个PTE,每个页面的大小为 2^12 = 4KB。
- 想象一个大的页表,我们(最终)将其称为二级页表;
- 我们希望对这个大页表应用Demand Paging,将这个大页表简单的看成内存而不是页表。所以我们可以在逻辑上将其分割成Page Size的小块。请注意,许多个(通常是1024或2048)PTE可以被装载在一个页面中,所以用于装载PTE的页面比原始PTE要少得多。
- 现在构造一个包含很多个PTE的第一级页表,第一级页表中的每个PTE指向第二级页表,第二级页表中的PTE指向实际的页面,因此第一级页表中每个PTE的大小相当于2^10 * 2^12;
- 第一级Page Table足够小,因此可以存储在内存中。它包含的每一个PTE指向了二级PT,那么这个PTE就可以代表那个二级PT中的所有PTE,如果一级页表中包含了1024个PTE,这也就意味着最大减少了1024倍的空间;
- 此时因为我们还有二级Page Table,我们让这个页表可以表示的世界变得更大而不是更小了!
- 但需要注意的是:不要在内存中存储那些所有的PTE都指向未使用内存的二级页表,因为显然不会使用到这个页表。这就是在(第二级)页表上使用请求分页!
上面的想法可以扩展到三个或更多层次。据我所知最大的有四个层次。我们只满足于两个层次。
Address Translation With a 2-Level Page Table二级页表的地址转换
PT1给出了第一级页表的索引,跟随相应PTE中的指针到达包含相关页框的二级页表。
PT2给出了这个第二层页表的索引,跟随相应PTE中的指针到达包含请求页面的页框。
Offset给出这个页框中最初请求的字所在位置的偏移量。
此时如果我们持有一个48位的虚拟地址,那么想要完成转换就变成了先取1-25位定位到二级页表,然后取26-35位在二级页表中找到对应的页框号,然后使用页框号*PageSize+Offset就完成了向物理地址的转换。
Summary of Last Lecture上次课的总结
- 从虚拟地址空间转换到物理地址空间:提升了多道程序设计的级别;避免了在实际内存中保留那些并不重要的材料;
- 使用TLB缓存加速对页表的引用;
- 不要再逻辑地址空间那个巨大的空洞上浪费页表的空间;(多级页表、段页管理);
posted on 2022-01-06 15:51 ThomasZhong 阅读(48) 评论(0) 编辑 收藏 举报