操作系统基础
yatbfm

注:大多数内容参考了JavaGuide

操作系统

虚拟内存

https://javaguide.cn/cs-basics/operating-system/operating-system-basic-questions-02.html#%E8%99%9A%E6%8B%9F%E5%86%85%E5%AD%98

  1. 什么是虚拟内存,有什么用?

虚拟内存是计算机系统内存管理的一个非常重要的技术。本质上来说它只是逻辑存在的,是一个假想出来的内存空间,主要作用是作为进程访问主存(物理内存)的桥梁并简化内存管理。
image.png
总结来说,虚拟内存主要提供了下面这些能力:

  • 隔离进程:物理内存通过虚拟地址空间访问,虚拟地址空间与进程一一对应。每个进程都认为自己拥有了整个物理内存,进程之间彼此隔离,一个进程中的代码无法更改正在由另一进程或操作系统使用的物理内存。
  • 提升物理内存利用率:有了虚拟地址空间后,操作系统只需要将进程当前正在使用的部分数据或指令加载入物理内存。
  • 简化内存管理:进程都有一个一致且私有的虚拟地址空间,程序员不用和真正的物理内存打交道,而是借助虚拟地址空间访问物理内存,从而简化了内存管理。
  • 多个进程共享物理内存:进程在运行过程中,会加载许多操作系统的动态库。这些库对于每个进程而言都是公用的,它们在内存中实际只会加载一份,这部分称为共享内存。
  • 提高内存使用安全性:控制进程对物理内存的访问,隔离不同进程的访问权限,提高系统的安全性。
  • 提供更大的可使用内存空间:可以让程序拥有超过系统物理内存大小的可用内存空间。这是因为当物理内存不够用时,可以利用磁盘充当,将物理内存页(通常大小为 4 KB)保存到磁盘文件(会影响读写速度),数据或代码页会根据需要在物理内存与磁盘之间移动。
  1. 没有虚拟内存有什么问题?
  • 用户程序可以访问任意物理内存,可能会不小心操作到系统运行必需的内存,进而造成操作系统崩溃,严重影响系统的安全
  • 同时运行多个程序容易崩溃。比如你想同时运行一个微信和一个 QQ 音乐,微信在运行的时候给内存地址 1xxx 赋值后,QQ 音乐也同样给内存地址 1xxx 赋值,那么 QQ 音乐对内存的赋值就会覆盖微信之前所赋的值,这就可能会造成微信这个程序会崩溃。
  • 程序运行过程中使用的所有数据或指令都要载入物理内存,根据局部性原理,其中很大一部分可能都不会用到,白白占用了宝贵的物理内存资源
  1. 虚拟地址和物理地址

物理地址(Physical Address)是真正的物理内存中地址,更具体点来说是内存地址寄存器中的地址。程序中访问的内存地址不是物理地址,而是虚拟地址(Virtual Address)
操作系统一般通过MMU(Memory Management Unit内存管理单元)将虚拟地址转换为物理地址,该过程称为地址翻译/地址转换(Address Translation)。
image.png
通过 MMU 将虚拟地址转换为物理地址后,再通过总线传到物理内存设备,进而完成相应的物理内存读写请求。
MMU翻译虚拟地址主要用三种方式:分段机制、分页机制和段页机制
现代操作系统广泛采用分页机制。

分段机制

分段机制(Segmentation) 以段(—段 连续 的物理内存)的形式管理/分配物理内存。应用程序的虚拟地址空间被分为大小不等的段,段是有实际意义的,每个段定义了一组逻辑信息,例如有主程序段 MAIN、子程序段 X、数据段 D 及栈段 S 等。

段表有什么作用?地址翻译过程是什么?

分段管理通过段表映射虚拟地址和物理地址。

虚拟地址由两部分组成:

  • 段号:标识该虚拟地址属于整个虚拟地址空间中的哪一段
  • 段内偏移量:相对于该段起始地址的偏移量

具体翻译过程:

  1. MMU首先解析虚拟地址中的段号
  2. 通过段号从段表中取出对应的段信息(段表项)
  3. 从段信息(段表项)中取出起始地址(物理地址)加上虚拟地址中的段内偏移量得到最终的物理地址

段表中还保存了段长(检查虚拟地址是否超出范围)、段类型(代码段、数据段等)等信息。

通过段号不一定找得到最终的物理地址,段表项可能不存在,因为:

  • 段表项被删除:软件错误、恶意行为等可能导致段表项被删除
  • 段表项还未创建:系统内存不足或者无法分配到连续的物理内存导致段表项无法被创建

分段机制为什么会导致内存外部碎片

外部内存碎片即段与段之间留下碎片空间(不足以映射给虚拟地址空间中的段),造成物理内存资源利用率降低。

分页机制

分页机制(Paging) 把主存(物理内存)分为连续等长的物理页,应用程序的虚拟地址空间划也被分为连续等长的虚拟页。现代操作系统广泛采用分页机制。

注意:这里的页是连续等长的,不同于分段机制下不同长度的段。

在分页机制下,应用程序虚拟地址空间中的任意虚拟页可以被映射到物理内存中的任意物理页上,因此可以实现物理内存资源的离散分配。分页机制按照固定页大小分配物理内存,使得物理内存资源易于管理,可有效避免分段机制中外部内存碎片的问题。

页表作用,地址翻译过程

分页管理通过页表映射虚拟地址和物理地址。分页机制中每个应用程序都会有一个对应的页表。虚拟地址由两部分组成:

  • 页号:通过虚拟页号找到对应的物理页号
  • 页内偏移量:物理页起始地址+页内偏移量=物理内存地址

具体翻译过程:

  1. MMU首先解析得到虚拟地址的虚拟页号
  2. 通过虚拟页号从页表中找到对应的物理页号(页表项)
  3. 物理页号对应的物理页起始地址+虚拟地址的业内偏移量得到最终的物理地址。

页表中还存有诸如访问标志(标识该页面有没有被访问过)、脏数据标识位等信息。

通过虚拟页号一定要找到对应的物理页号吗?找到了物理页号得到最终的物理地址后对应的物理页一定存在吗?

不一定!可能会存在页缺失。也就是说,物理内存中没有对应的物理页或者物理内存中有对应的物理页但虚拟页还未和物理页建立映射(对应的页表项不存在)。

单级页表有什么问题?为什么需要多级页表

只用一级页表的话,如果系统运行的程序多起来,页表的开销很大,占用空间,而且绝大多数程序可能只用到页表中的几项,其他的浪费了。采用二级页表的话,分为一级页表和二级页表,一级页表对应的二级页表是一对多的关系,二级页表是按需加载的,进而节省空间。

多级页表

多级页表属于时间换空间,利用增加页表的查询次数减少页表占用的空间。

TLB作用?有TLB时候的地址翻译过程是什么

为了提高虚拟地址到物理地址的转换速度,操作系统在页表方案基础之上引入了转址旁路缓存(Translation Lookaside Buffer,TLB,也被称为快表)

一般来说,TLB属于MMU内部的单元,本质是一块高速缓存,缓存了虚拟页号和物理页号的映射关系。

使用 TLB 之后的地址翻译流程是这样的:

  1. 用虚拟地址中的虚拟页号作为 key 去 TLB 中查询;
  2. 如果能查到对应的物理页的话,就不用再查询页表了,这种情况称为 TLB 命中(TLB hit)。
  3. 如果不能查到对应的物理页的话,还是需要去查询主存中的页表,同时将页表中的该映射表项添加到 TLB 中,这种情况称为 TLB 未命中(TLB miss)。
  4. 当 TLB 填满后,又要登记新页时,就按照一定的淘汰策略淘汰掉快表中的一个页。

中断、软中断

进程和线程的区别

线程和协程的区别

进程调度算法

用户态和内核态的区别

内存对齐

由 Hexo 驱动 & 主题 Keep
访客数 访问量