17.内存分区与分页

【README】

1.本文内容总结自 B站 《操作系统-哈工大李治军老师》,内容非常棒,墙裂推荐;

2.程序使用内存的3个步骤:

  • 步骤1:把程序分为多个段,包括代码段,数据段;这是编译要做的事情;
  • 步骤2:在内存中找一段空闲内存(或空闲分区);
  • 步骤3:一旦找到空闲分区,就把磁盘上的程序的段内容读入到空闲分区;在读的过程中,需要把LDT初始化好,LDT存储了段序号与段基址的映射关系;

【1】内存分区

1)内存分区: 内存如何分割,以便把程序的各个段载入到相应的内存分区;
简单地,内存分区指的是划分的一段用于存储程序段(或代码段cs,或数据段ds)的内存空间

【1.1】固定分区与可变分区

1)固定分区
等分,操作系统初始化时把内存等分为k个分区;
但是段长度有大有小,固定分区不能满足段长度不定的业务场景;

 


【1.2】可变分区管理

1)核心数据结构

  • 空闲分区表:存储空闲的内存分区数据(或段释放后的内存空间列表);
  • 已分配分区表:已使用的内存分区的记录信息;
  • 注意:分区信息只需要记录 分区基址 和 长度 这两种信息

2) 请求分配内存

【图解】

  • 目前空闲的内存地址空间为 250K~500K;
  • 而段3内存请求分配100K,则把250K~350K分配给该段3(seg3);并新增一条已分配分区表记录;

3)释放内存
【例】段2不再需要,释放段2的内存
同时把释放出的内存更新到空间分区表,从已分配分区表中移除段2的记录;


4)再次申请
此时空闲分区表如下:

内存分区序号

基址

长度

1

350K

150K

2

200K

50K


【1.3】内存分区分配算法

内存请求分配40K,又分区1有150K,分区2有50K,那应该分配分区1还是分区2给到这个请求?

  • 首先适配:(350, 150),挑选空闲分区表中第一条且分区空间足够大的分区来分配;空闲分区表查询足够快;
  • 最佳适配:(200, 50),内存空间浪费少,但空闲分区大小会越来越小,分割后产生的内存碎片比较多;
  • 最差适配:(350, 150),挑选最大的分区进行分配,内存空间浪费多,但空闲分区大小比较均匀,内存碎片少;

 

 
【例】哪种内存分区分配算法最好


【2】 内存分页

【2.1】内存碎片问题

0)问题:内存分区导致的内存碎片问题

  • 解决方法:引入分页解决内存分区导致的内存碎片的问题;
  • 实际的物理内存分配是采用分页而不是分区; (补充:虚拟内存是采用分区来分割或分配的)

 【图解】内存碎片问题:

  • 如上图所示,申请大小为160K的内存空间,而空闲分区表中的2个分区大小均小于160K且他们不是连续内存地址空间,所以无法直接分配160K的内存空间(需要先做空闲分区合并,把碎片收集在一起),即使总的内存大小为200K(大于160K);

1)内存碎片:

  • 可用的总内存大小大于申请的内存大小,但内存分区不连续,且每个分区小于申请大小,导致内存申请失败;

2)解决方法

  • 内存紧缩;简单说,把白色的分区合并在一起,彩色分区合并在一次,这就需要复制段内容;

3)内存紧缩带来的问题(内存紧缩耗时耗力

  • 需要修改段基址的LDT,非常麻烦;
  • 在内存紧缩过程中,上层用户应用程序无法执行,因为程序的多个段在复制内容到新的内存空间,段基址需要级联修改;
  • 内存紧缩耗时长,容易导致机器假死;

小结: 内存紧缩方法解决内存碎片是不可行的;从而引出了内存分页解决内存碎片问题


【2.2】内存分页

1)定义:操作系统初始化时,物理内存空间就分为多个页,每页占用4K内存 大小;
在处理段内存申请时,以页为单位把内存分配给段,如下表:

                                                                 表2 内存分页表

物理内存页序号(页框号)

7

段0

页3

6

段0

页0

5(空闲页)

4(空闲页)

3

段0

页2

2(空闲页)

1

段0

页1

0(空闲页)

 

 2)内存分页优点:

  • 优点1:不存在内存碎片,因为中间的空闲页可以分配给其他进程;
  • 优点2:内存浪费少:一个段最多浪费1页,即一个段最多浪费4K(一个段由多个页组成);

【小结】

  • 物理内存采用分页进行分割和分配,减少了内存浪费,避免了内存碎片;
  • 用户希望把程序分为多个段;
  • 综上,操作系统需要既支持分段也支持分页对内存进行分割和分配;

【例】以页为单位的内存分配

 【问题】jmp 40 映射到哪个页?

  • 内存页的分配情况,通过页表进行记录,且每个进程都有一个页表;页表寄存器时 CR3;其中页表基址存入进程的PCB;  

【例】mov [0x2240], %eax  

  • 步骤1:0x2240 除以4K,即右移12位,得到页号为0x02, 偏移地址0x240;
  • 步骤2:通过页号2找到叶框号为3;
  • 步骤3: 得到物理地址0x3240 ;(3乘以4K,3左移12位得到基址0x3000);
  • 步骤4: 页框3的基址为0x3000,偏移地址0x240,所以得到的物理地址为0x3000 + 0x240得到0x3240 ;
  • 补充:把逻辑地址0x2240根据CR3存储的页表基址,可以翻译为物理地址 0x3240,这个内存地址翻译过程是由MMU完成的

【小结】

  • 一个程序由多个段组成;
  • 每个段内容分散存储在内存中的多个页;每个段不是直接存入内存(那样会造成内存碎片与浪费);
  • 为了在程序执行时能够实现重定位(找到段基址加上偏移地址得到物理内存地址),就需要建立页表存储页号与页框号映射关系,而找到页框号就可以计算出内存页基址;
  • 因为每页大小4K,用过页框号乘以4K就得到页基址了;
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值