内存管理

一、虚拟内存


操作系统引入了虚拟内存,进程持有的虚拟地址会通过 CPU 芯片中的内存管理单元(MMU)的映射关系,来转换变成物理地址,然后再通过物理地址访问内存

二、如何管理虚拟地址与物理地址之间的关系

  • 内存分段

虚拟地址是通过段表与物理地址进行映射的,分段机制会把程序的虚拟地址分成 4 个段,每个段在段表中有一个项,在这一项找到段的基地址,再加上偏移量,于是就能找到物理内存中的地址

不足之处
1. 内存碎片(外部内存碎片+内部内存碎片)
- 外部内存碎片,也就是产生了多个不连续的小物理内存,导致新的程序无法被装载;
- 内部内存碎片,程序所有的内存都被装载到了物理内存,但是这个程序有部分的内存可能并不是很常使用,这也会导致内存的浪费;
2. 内存交换效率低
- 产生了内存碎片,那不得不重新 Swap 内存区域,这个过程会产生性能瓶颈。如果内存交换的时候,交换的是一个占内存空间很大的程序,这样整个机器都会显得卡顿。
  • 内存分页

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

image

CPU 直接通过 MMU,找出实际要访问的物理内存地址。当进程访问的虚拟地址在页表中查不到时,系统会产生一个缺页异常,进入系统内核空间分配物理内存、更新进程页表,最后再返回用户空间,恢复进程的运行。
  1. 分页是怎么解决分段的内存碎片、内存交换效率低的问题
分页释放的内存都是以页为单位释放的,也就不会产生无法给进程使用的小内存。如果内存空间不够,操作系统会把其他正在运行的进程中的「最近没被使用」的内存页面给释放掉,也就是暂时写在硬盘上,称为换出(Swap Out)。一旦需要的时候,再加载进来,称为换入(Swap In)。所以,一次性写入磁盘的也只有少数的一个页或者几个页,不会花太多时间,内存交换的效率就相对比较高。

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

  1. 分页机制下,虚拟地址和物理地址是如何映射的
   1. 把虚拟内存地址,切分成页号和偏移量;
   2. 根据页号,从页表里面,查询对应的物理页号;
   3. 直接拿物理页号,加上前面的偏移量,就得到了物理内存地址。
  1. 简单的分页有什么缺陷吗?
有空间上的缺陷。因为操作系统是可以同时运行非常多的进程的,那这不就意味着页表会非常的庞大。在 32 位的环境下,虚拟地址空间共有 4GB,假设一个页的大小是 4KB(2^12),那么就需要大约 100 万 (2^20) 个页表项,每个「页表项」需要 4 个字节大小来存储,那么整个 4GB 空间的映射就需要有 4MB 的内存来存储页表。这 4MB 大小的页表,看起来也不是很大。但是要知道每个进程都是有自己的虚拟地址空间的,也就说都有自己的页表。那么,100 个进程的话,就需要 400MB 的内存来存储页表,这是非常大的内存了,更别说 64 位的环境了。
  1. 如果解决简单的分页缺陷的
- 多级页表:页表(一级页表)分为 1024 个页表(二级页表),每个表(二级页表)中包含 1024 个「页表项」,形成二级分页
- 局部性原理 每个进程都有 4GB 的虚拟地址空间,而显然对于大多数程序来说,其使用到的空间远未达到 4GB,因为会存在部分对应的页表项都是空的,根本没有分配,对于已分配的页表项,如果存在最近一定时间未访问的页表,在物理内存紧张的情况下,操作系统会将页面换出到硬盘,也就是说不会占用物理内存。
- 对于 64 位的系统,两级分页变成四级目录
  1. 页表缓存
利用程序的局部性,在CPU 芯片中,加入了一个专门存放程序最常访问的页表项的 Cache,这个 Cache 就是 TLB(Translation Lookaside Buffer) ,通常称为页表缓存、转址旁路缓存、快表等
  • 段页式内存
1. 访问段表,得到页表起始地址;
2. 访问页表,得到物理页号;
3. 将物理页号与页内位移组合,得到物理地址。

参考链接

posted @ 2022-02-21 11:04  曾某某scau  阅读(57)  评论(0编辑  收藏  举报