Cwww3's Blog

Record what you think

0%

memory

物理内存,大小有限,多个程序使用,不易分配。

引入虚拟地址,程序的视角认为整个内存只有它在使用。程序间相互隔离,互不影响。

CPU 中的内存管理单元(MMU),负责将虚拟地址转化为实际的物理地址。

管理虚拟地址和物理地址

分段

程序由若干个逻辑分段组成,代码分段、数据分段、栈段、堆段组成。虚拟地址由两部分组成,段选择因子段内偏移量。根据段选择因子可以从存储在内存中的段表中找到段基地址,再根据段内偏移量,得到真正的物理地址。段选择因子还包含了其他信息,段界限(限制段的大小),特权级 DPL(读/写控制)

问题:

内存碎片,会产生多个不连续的物理内存,导致新的程序无法被装载。

内存浪费,程序的所有内存都被装载到物理内存,但是有部分内存并不常用。

解决:

内存交换,对于不连续的内存,可以读入到磁盘,再从磁盘中读出,连续地存入内存(Swap)

问题:

如果频繁的进行内存交换,且交换的是内存占用很大的程序,那么效率肯定会很低。引入分页解决

分页

优化交换的内存大小,让需要交换写入或者从磁盘装载的数据更少一点。

分页是把整个虚拟和物理内存空间切成一段段固定尺寸的大小——页(Page).虚拟地址和物理地址的映射通过存储在内存中的页表来映射。页表保存所有虚拟地址和物理地址的映射

如果内存空间不够,操作系统会把其他正在运行的进程中的最近没被使用的内存页面给释放掉,暂时暂时卸载硬盘上(Swap Out),一旦需要,再加载进来(Swap In)。每次交换的大小就是一个页或者几个页,提升了交换的效率。

分页使得我们在加载程序的时候,不再需要一次性把程序加载到物理内存中,而只有在程序运行中,需要用到对应虚拟内存页里面的指令和数据时,再加载到物理内存里。

在分页机制下,虚拟地址分为页号业内偏移,根据页号,能从页表中获取物理内存的基地址,再根据业内偏移得到物理内存地址。

问题:

因为页表存储的是整个虚拟地址和物理地址的映射,那么存储一个页表所需的内存会比较多,且每一个程序都会拥有一个自己的页表,那会导致很大一部分内存用于存储页表信息。

解决:

多级页表(Multi-Level Page Table)

一级页表中存储 1024 个页表项(覆盖整个虚拟空间的大小,相比原来一级分页中的页表空间占用小了很多),根据页表项中的信息,可以得到二级页表中的页表项,再根据二级页表中的页表项得到物理地址。

根据局部性原理,每个进程都有 4GB 的虚拟空间,显然,其使用的空间远未达到 4GB,因为存在部分的页表项是空的,根本没有分配,对于已分配的页表项,如果一定时间未访问,在物理内存紧张的情况下,也会被换出到因硬盘。

所以如果使用了二级分页,如果一级页表的页表项没有被分配,就不需要创建二级页表了,这样就能减少页表对内存的占用。

问题:

虽然在空间上减少了占用,但是由于采用了多级映射的原因,导致地址转换的速度变慢了。

解决:

还是程序局部性原理,在一段时间内,整个程序的执行仅限于程序中的某一部分。相应地,执行所访问的存储空间也局限于某个内存区域。利用这一特性,科学家在 CPU 芯片中,加入了一个专门存放程序最常访问的页表项的 Cache——TLB.

段页式

分段和分页并不是对立的,可以组合起来使用。

  1. 现将程序划分为多个有逻辑意义的段
  2. 再将每个段分为多个页

Donate comment here.