《操作系统》内存分段和分页 | 青训营笔记

690 阅读4分钟

前言

这是我参与「第三届青训营 -后端场」笔记创作活动的的第4篇笔记。

为了更加有效地管理内存并且少出错,现代系统提供了一种对主存的抽象概念,叫做虚拟内存(VM)。

虚拟内存是硬件异常、硬件地址翻译、主存、磁盘文件和内核软件的完美交互,它为每个进程提供了一个大的、一致的和私有的地址空间。

通过一个很清晰的机制,虚拟内存提供了三个重要的能力:

  1. 它将主存看成是一个存储在磁盘上的地址空间的高速缓存,在主存中只保存活动区域,并根据需要在磁盘和主存之间来回传送数据,通过这种方式,它高效地使用了主存。
  2. 它为每个进程提供了一致的地址空间,从而简化了内存管理。
  3. 它保护了每个进程的地址空间不被其他进程破坏。

内存分段

程序是由若干个逻辑分段组成的,如可由代码分段、数据分段、栈段、堆段组成。不同的段是有不同的属性的,所以就用分段(Segmentation) 的形式把这些段分离出来。

分段机制下虚拟地址和物理地址如何映射

图片.png

  • 段选择因子就保存在段寄存器里面。段选择子里面最重要的是段号,用作段表的索引
  • 段表里面保存的是这个段的基地址、段的界限和特权等级等。
  • 虚拟地址中的段内偏移量应该位于0和段界限之间,如果段内偏移量是合法的,就将段基地址加上段内偏移量得到物理内存地址。

图片.png

内存分页

分段的好处就是能产生连续的内存空间,但是会出现内存碎片和内存交换的空间太大的问题。

要解决这些问题,那么就要想出能少出现一些内存碎片的办法。另外,当需要进行内存交换的时候,让需要交换写入或者从磁盘装载的数据更少一点,这样就可以解决问题了。这个办法,也就是内存分页( Paging) 。

分页是把整个虚拟和物理内存空间切成一段段固定尺寸的大小。这样一个连续并且尺寸固定的内存空间,我们叫页(Page)。在Linux下,每一页的大小为4KB。

虚拟地址和物理地址之间通过页表转换

图片.png

分页怎么解决分段的内存碎片、内存交换效率低的问题

由于内存空间都是预先划分好的,也就不会像分段会产生间隙非常小的内存,这正是分段会产生内存碎片的原因。而采用了分页,那么释放的内存都是以页为单位释放的,也就不会产生无法给进程使用的小内存。

如果内存空间不够,操作系统会把其他正在运行的进程中的【最近没被使用】的内存页面给释放掉,也就是暂时写在硬盘上,称为换出(Swap Out)。一旦需要的时候,再加载进来,称为换入(Swap In)。所以,一次性写入磁盘的也只有少数的一个页或者几个页,不会花太多时间,内存交换的效率就相对比较高。

图示:

图片.png

分页的方式使得我们在加载程序的时候,不再需要一次性都把程序加载到物理内存中。

我们完全可以在进行虚拟内存和物理内存的页之间的映射之后,并不真的把页加载到物理内存里,而是只有在程序运行中,需要用到对应虚拟内存页里面的指令和数据时,再加载到物理内存里面去。

分页机制下虚拟地址和物理地址如何映射

图片.png

总结,对于一个内存地址转换,就是这样三个步骤:

  1. 把虚拟内存地址,切分成页号和偏移量;
  2. 根据页号,从页表里面,查询对应的物理页号;
  3. 直接拿物理页号,加上前面的偏移量,就得到了物理内存地址。