操作系统-内存管理

虚拟内存

操作系统会提供⼀种机制,将不同进程的虚拟地址和不同内存的物理地址映射起来。

两个概念:

  • 程序所使⽤的内存地址叫做虚拟内存地址(Virtual Memory Address)
  • 实际存在硬件⾥⾯的空间地址叫物理内存地址(Physical Memory Address)

管理虚拟地址与物理地址的两种方式:

  • 内存分段管理
  • 内存分页管理
     

内存分段

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

分段机制下的虚拟地址由两部分组成,段选择因子和段偏移量

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

不足之处:

  • 第⼀个就是内存碎⽚的问题。
  • 第⼆个就是内存交换的效率低的问题。
     

内存碎片问题

假设有 1G 的物理内存,⽤户执⾏了多个程序,其中:

  • 游戏占⽤了 512MB 内存
  • 浏览器占⽤了 128MB 内存
  • ⾳乐占⽤了 256 MB 内存

这个时候,如果我们关闭了浏览器,则空闲内存还有 1024 - 512 - 256 = 256MB。
如果这个 256MB 不是连续的,被分成了两段 128 MB 内存,这就会导致没有空间再打开⼀个 200MB 的程序。

产生碎片的地方:

  • 外部内存碎⽚,也就是产⽣了多个不连续的⼩物理内存,导致新的程序⽆法被装载;
  • 内部内存碎⽚,程序所有的内存都被装载到了物理内存,但是这个程序有部分的内存可能并不是很常使⽤,这也会导致内存的浪费

解决:内存交换

可以把⾳乐程序占⽤的那 256MB 内存写到硬盘上,然后再从硬盘上读回来到内存⾥。不过再读回的时候,我们不能装载回原来的位置,⽽是紧紧跟着那已经被占⽤了的 512MB 内存后⾯。
 

内存交换效率低

因为硬盘的访问速度要⽐内存慢太多了,每⼀次内存交换,我们都需要把⼀⼤段连续的内存数据写到硬盘上。
所以, 如果内存交换的时候,交换的是⼀个占内存空间很⼤的程序,这样整个机器都会显得卡顿
 

内存分页

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

⽽当进程访问的虚拟地址在⻚表中查不到时,系统会产⽣⼀个缺⻚异常,进⼊系统内核空间分配物理内存、更新进程⻚表,最后再返回⽤户空间,恢复进程的运⾏。
 

内存碎片、内存交换效率低解决

由于内存空间都是预先划分好的,也就不会像分段会产⽣间隙⾮常⼩的内存,这正是分段会产⽣内存碎⽚的原因。⽽采⽤了分⻚,那么释放的内存都是以⻚为单位释放的,也就不会产⽣⽆法给进程使⽤的⼩内存。
如果内存空间不够,操作系统会把其他正在运⾏的进程中的「最近没被使⽤」的内存⻚⾯给释放掉,也就是暂时写在硬盘上,称为换出(Swap Out)。⼀旦需要的时候,再加载进来,称为换⼊(Swap In)。所以,⼀次性写⼊磁盘的也只有少数的⼀个⻚或者⼏个⻚,不会花太多时间, 内存交换的效率就相对⽐较⾼
 

映射过程

简单分页缺陷

在 32 位的环境下,虚拟地址空间共有 4GB,假设⼀个⻚的⼤⼩是 4KB(2^12),那么就需要⼤约 100 万(2^20) 个⻚,每个「⻚表项」需要 4 个字节⼤⼩来存储,那么整个 4GB 空间的映射就需要有 4MB的内存来存储⻚表。
100 个进程的话,就需要 400MB 的内存来存储⻚表,这是⾮常⼤的内存了,更别说 64 位的环
境了。


 解决:多级页表

我们把这个 100 多万个「⻚表项」的单级⻚表再分⻚,将⻚表(⼀级⻚表)分为 1024 个⻚表(⼆级⻚表),每个表(⼆级⻚表)中包含 1024 个「⻚表项」,形成⼆级分⻚。如下图所示
 

你可能会问,分了⼆级表,映射 4GB 地址空间就需要 4KB(⼀级⻚表) + 4MB(⼆级⻚表)的内存,这样占⽤空间不是更⼤了吗?
当然如果 4GB 的虚拟地址全部都映射到了物理内存上的话,⼆级分⻚占⽤空间确实是更⼤了,但是,我们往往不会为⼀个进程分配那么多内存。
 

如果某个⼀级⻚表的⻚表项没有被⽤到,也就不需要创建这个⻚表项对应的⼆级⻚表了,即可以在需要时才创建⼆级⻚表。
 

对于 64 位的系统,两级分⻚肯定不够了,就变成了四级⽬录,分别是:

  • 全局⻚⽬录项 PGD(Page Global Directory);
  • 上层⻚⽬录项 PUD(Page Upper Directory);
  • 中间⻚⽬录项 PMD(Page Middle Directory);
  • ⻚表项 PTE(Page Table Entry);
     

问题:页表的级数较多,两个地址之间的转化较为缓慢

解决:TLB

就可以利⽤这⼀特性,把最常访问的⼏个⻚表项存储到访问速度更快的硬件,于是计算机科学家们,就在 CPU 芯⽚中,加⼊了⼀个专⻔存放程序最常访问的⻚表项的 Cache,这个 Cache 就是 TLB(Translation Lookaside Buffer) ,通常称为⻚表缓存、转址旁路缓存、快表等。

段页式管理

段⻚式内存管理实现的⽅式:

  • 先将程序划分为多个有逻辑意义的段,也就是前⾯提到的分段机制;
  • 接着再把每个段划分为多个⻚,也就是对分段划分出来的连续空间,再划分固定⼤⼩的⻚;
     

地址结构就由段号、段内⻚号和⻚内位移三部分组成。


段⻚式地址变换中要得到物理地址须经过三次内存访问:

  • 第⼀次访问段表,得到⻚表起始地址;
  • 第⼆次访问⻚表,得到物理⻚号;
  • 第三次将物理⻚号与⻚内位移组合,得到物理地址。
     

 

  • 30
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值