当前位置: 首页 > news >正文

内存管理 : 02 内存分区与分页

从我的视角看内存管理课程内容

在操作系统的知识体系中,内存管理占据着极为关键的地位。我在上节课开启了内存管理的学习之旅,深知它与CPU管理一同构成了操作系统的核心支柱,这两部分管理妥善后,一个基础的操作系统雏形便得以显现,再融入设备驱动和文件系统,一个完整可用的小型操作系统就能诞生。所以,今天我要继续深入探索内存管理的奥秘。

回顾上节课内容

本次学习,我首先对上次课的知识进行回顾,目的有二:其一,加深对已学内容的理解与认识;其二,通过回顾引出新问题,为后续学习做好铺垫。实际上,上次所学内容尚未形成完整体系,存在的缺口正是今天要学习的重点,补上这部分内容后,知识框架才能完整。

内存分区在整个知识脉络中起着承上启下的作用,它引出的问题将带领我走进今天的新主题——分页。在此之前,我们主要探讨了分段管理方式,而今天,分页的概念将登场,最终我会明白分段与分页相结合,才是操作系统内存管理的真正模样。

我回忆起,操作系统管理内存的核心思想是让内存高效利用起来。基于冯诺依曼存储程序的思想,计算机的工作流程是将程序载入内存,再由CPU取指执行,在这个过程中,内存得以被使用。一个程序通常会被分为多个段,比如代码段和数据段,这样划分是因为不同段具有不同特性,符合编程习惯和程序运行需求。

当程序分段完成后,需要将其放置在内存中。具体做法是寻找空闲内存区域,比如将代码段存放在地址3000开始的合适空间,数据段放在地址1000开始的空闲处。但程序在内存中的地址并非固定不变,以代码段中“jump 40”这条指令为例,它实际要跳转到的地址应该是3040,这就需要进行重定位操作。我们通过建立段表来记录各段在内存中的起始地址,利用硬件设备结合段表寄存器LDTR实现运行时重定位,从而确保程序正确执行。

在多进程环境下,每个进程都有独立的段表LDT,进程切换时,PCB和LDTR随之切换,使得不同进程在各自的地址空间内运行,互不干扰。这部分知识与之前学习的多进程映射表相关联,实际上映射表就是这里的LDT。我深知,要真正掌握这些知识,仅靠课堂听讲远远不够,还需亲自完成实验六,通过实践加深理解。

引出内存分区

回顾完上节课内容,我开始思考程序放入内存的具体流程,这可概括为三步:第一步,程序分段,这由编译环节负责;第二步,在内存中寻找空闲分区,这正是今天的学习重点;第三步,将程序载入内存,同时初始化LDT并与PCB关联,此过程涉及后续要学的文件系统、设备驱动等知识。这三个步骤看似简单,却涵盖了编译、算法数据结构、内存管理、进程管理等多方面知识,充分体现了操作系统的系统性。

内存分区的方法在这里插入图片描述

在这里插入图片描述
接下来,我学习了内存分区的两种方法。第一种是固定分区,它如同将面包平均分给孩子,把内存等分成若干个大小相同的分区。但这种方法存在明显缺陷,因为程序对内存的需求大小各异,固定分区无法满足多样化需求,所以实际应用中并不合适。

第二种是可变分区,它更加灵活,能根据程序请求的内存大小,在空闲分区中划分相应区域。在这里插入图片描述在这里插入图片描述

例如,内存中0 - 100k被操作系统占用,100k - 200k被segment1使用,250k - 500k为空闲区域,当有100k的内存请求时,就从250k处划分出100k,划分后空闲分区和已分配分区信息都要更新。在这里插入图片描述
而且,当进程结束释放内存时,空闲分区表也会相应变化。

当存在多个空闲分区都能满足请求时,就需要选择合适的分区算法。在这里插入图片描述
常见的算法有最佳适配、最差适配和首次适配。最佳适配会选择最接近请求大小的空闲分区,这样会导致空闲分区逐渐变小,产生大量内存碎片;最差适配则选择最大的空闲分区,能使剩余空闲分区大小相对均匀;首次适配不考虑分区大小差异,直接选择第一个满足条件的分区,其优点是查找速度快,时间复杂度为O(1),而最佳适配和最差适配的时间复杂度为O(n)。这些算法各有优劣,在实际操作系统中,需根据内存使用特点综合选择,通常不会单纯使用某一种。实际上,物理内存最终是通过分页来分配,而内存分区算法主要用于虚拟内存处理,这一点我先记下,待后续学习虚拟内存时再深入理解。

分页的引入在这里插入图片描述

内存分区方法存在效率问题,其中最突出的是内存碎片。由于不断的请求和释放操作,无论采用哪种适配算法,都会产生内存碎片。在这里插入图片描述
当有160k的内存请求时,虽然总空闲内存为200k,但因碎片分散,无法满足请求。为解决碎片问题,可能会想到内存紧缩,即将已使用内存区域合并,释放出连续的大空间,但这会耗费大量时间,在紧缩过程中,CPU无法执行用户进程,导致上层用户程序无法运行,出现类似死机的现象,随着内存容量增大,这种方法愈发不可行。
在这里插入图片描述

于是,分页的解决方案应运而生。它将内存和程序请求都划分为固定大小的页,物理内存初始化时就被分成一页页,以4k为一页为例,通过map映射表记录每一页的使用状态。程序请求内存时,根据需求计算所需页数并向上取整,然后在物理内存中寻找空闲页进行分配。分页的优势在于避免了内存碎片问题,即使存在未被完全使用的页,浪费的内存最多也只是一页(4k),相比内存分区产生的大量碎片,浪费大大减少,而且无需进行耗时的内存紧缩操作。从物理内存角度,分页能有效减少浪费;从用户角度,用户习惯程序分段编写,所以操作系统需要同时支持分段和分页,这也是后续学习的重点。

分页后的地址计算与重定位在这里插入图片描述

程序通过分页方式放入物理内存后,仍面临程序执行的问题。以“jump 40”指令为例,需要确定40这个地址分配到了哪一页,以及最终要发出的地址是多少。假设每页大小为40,40位于第零页,如果它对应的物理页框是第五个,那么最终地址就是540。

计算最终地址需要借助页表,就像分段时使用段表进行重定位一样。页表也有对应的寄存器CR3,每个进程都有独立页表,进程切换时CR3随之切换。在实际计算中,以地址2240(16进制)为例,由于每页大小为4k(2的12次方),将地址右移12位,可得到页号为2,页内偏移保留。通过页号在页表中查找对应的页框号,假设页框号为3,因为每页4k,所以物理地址就是3×4k + 页内偏移,即3240。这些计算操作由硬件的内存管理单元MMU自动完成,只要将地址和页表起始地址提供给MMU,它就能根据页表进行重定位,计算出正确的物理地址。

至此,我对内存管理的学习有了更深入的认识。一个程序从分段开始,经过内存分区、分页,最终通过页表实现地址重定位并正确执行,这些知识相互关联,共同构建起操作系统内存管理的基本轮廓。后续我还将学习分段与分页的结合,进一步完善对内存管理的理解。

相关文章:

  • leetcode2025. 分割数组的最多方案数-hard
  • 除自身以外数组的乘积与加油站问题:算法揭示数据中的隐藏关系与环路行驶的最优解
  • 图片批量压缩转换格式 JPG/PNG无损画质 本地运行
  • Java 可扩展状态系统设计:备忘录模式的工程化实践与架构演进
  • 6个跨境电商独立站平台
  • 理解 Redis 事务-21(使用事务实现原子操)
  • docker 镜像完整生成指南
  • 论文阅读笔记——Janus,Janus Pro
  • RabbitMQ 集群与高可用方案设计(一)
  • 嵌入式硬件---施密特触发器单稳态触发器多谐振荡器
  • Redis实战-缓存篇(万字总结)
  • uniapp报错mongo_cell_decision_not_found
  • TCP 和 UDP 的区别
  • Windows逆向工程提升之x86结构化异常SEH处理机制
  • 非接触式互连:当串扰是您的朋友时
  • npm修改镜像的教程,将npm镜像修改为国内地址增加下载速度
  • SpringBoot-11-基于注解和XML方式的SpringBoot应用场景对比
  • Kubernetes(k8s)全面解析:从入门到实践
  • 以前端的角度理解 Kubernetes(K8s)
  • xy坐标上如何判定两个矩形是否重合
  • 武昌网站建设哪家便宜/seo排名优化公司价格
  • 装修公司合作平台的网站/软文营销
  • 沂源网站开发/互动营销案例
  • 郑州大学动态网站开发考试答案/公司做网页要多少钱
  • wordpress主题教程黄聪/杭州seo俱乐部
  • 工程项目网站/如何进行搜索引擎的优化