1.1 存储管理 逻辑物理地址
存储/内存管理的功能
- 内存空间分配和回收:是存储管理的主要内容。
- 地址变换:可执行文件生成中的链接技术、程序加载时的重定位技术,进程运行时硬件和软件的地址变换技术和机构。
- 存储/内存共享:代码和数据共享,对地址空间的访问权限(读、写、执行)。
- 存储保护:保证各道作业在各自的存储空间内运行,互不干扰
- 内存空间扩充:它涉及存储器的逻辑组织和物理组织;
- 由应用程序控制:覆盖;
- 由OS控制:交换(整个进程空间),请求调入和预调入(部分进程空间)
存储管理的基本机制
- 地址空间/逻辑地址空间:一个进程所能够用于访问内存的地址集合。地址空间是逻辑地址的集合
- 存储空间/物理地址空间:存储空间是指主存中一系列存储信息的物理单元的集合,这些单元的编号称为物理地址或绝对地址。存储空间是物理地址的集合
- 逻辑地址:又称虚拟地址/相对地址,程序所使用的地址。进程在运行时,看到和使用的地址都是逻辑地址。用户程序和程序员只需知道逻辑地址。不同进程可以有相同逻辑地址(反正这些逻辑地址可以映射到贮存的不同位置)
- 物理地址:
存储管理的基石:
- 地址独立:程序发出的地址与物理地址无关
- 地址保护:一个程序不能访问另一个程序的地址空间
1.2 程序链接与装入
创建进程首先要将程序和数据写入内存。将用户源程序变为可在内存中执行的程序,需要进行以下几个步骤
-
编译:源代码(.c)——>若干目标模块(.o) 翻译为机器语言
【编译后的所有目标模块都是从0开始的相对地址/逻辑地址】
-
链接:链接程序将 目标模块+所需库函数——>可装载模块(可执行文件).exe
-
静态链接:(在编译时完成链接)用户一个工程中所需的多个程序采用静态链接的方式链接在一起。当我们希望共享库的函数代码直接链接入程序代码中,也采用静态链接方式。
当链接成一个装入模块时要 修改相对地址,将所有的外部调用符号也变换为相对地址
-
装入时动态链接:在装入内存时,采用边装入边链接的方式。
优点:便于修改和更新,便于实现对目标模块的共享
-
运行时动态链接:在运行时需要某些目标模块时,才进行链接,常用于链接共享库代码,加快程序的装入且节省内存空间,但相比静态链接较慢
-
链接过程的本质:合并相同的“节”(.text,.data,.bss)
-
-
装入:由装载程序将可装载入模块装入内存
- 绝对装入:(不重要)只适用于单道程序环境。编译时知道程序驻留在内存的某个位置,编译程序将产生绝对地址的目标代码,装入程序按照装入模块中的地址,将程序和数据装入内存。
- 可重定位装入/静态重定位:根据内存情况,将装入模块装入内存的适当位置。地址变换是在进程装入时一次完成的。
- 在装入时对目标程序中指令和数据地址的修改过程称为重定位
- 当一个作业装入内存时,必须给它分配要求的全部内存空间,若无足够的内存,则无法装入。作业一旦进入内存,则在运行期间就不能在内存中移动,也不能再申请内存空间
- 动态运行是装入/动态重定位:程序在内存中的位置经常要改变。装入程序把装入模块装入内存后,并不立即把装入模块中的相对地址转换为绝对地址,而是把这种地址转换推迟到程序真正执行时才进行。因此,装入内存后的所有地址均为相对地址。
- 需要重定位寄存器,在程序运行过程中进行地址转换。
- 优点:可以将程序分配到不连续的存储区;在程序运行之前可以只装入部分代码即可投入运行,在运行期间可以动态申请分配内存;便于程序段的共享
【链接后形成完整的逻辑地址】
程序块:
- 一个程序本质上都是由bss段、data段、text段三个组成
- 编译完成后
- bss段:存放未初始化和所有初始化为0的全局变量和静态变量∈静态内存分配
- data段(segment):存放已初始化的全局变量和静态变量∈静态内存分配
- text段:代码段,用于存放程序执行代码的一块内存区域。这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于只读(某些架构允许可写)
- text和data段都在可执行文件中,由系统从可执行文件中加载。bss不在可执行文件中,由系统初始化。
- 一个装入内存的可执行程序
-
-
栈:存放、交换临时变量的内存区。实现函数调用
- 存放局部变量,但不包括static。static意味着在数据段存放变量
- 保护/恢复函数调用,递归调用时可以保存上一次的值
- 往低地址方向增长
-
堆:存放进程运行中动态分配的内存段
- 使用malloc等函数分配内存时,新分配的内存就被动态添加到堆上(往高地址方向增长);当利用free等函数释放内存时,被释放的内存从堆中被剔除
-
扩展:
Linux下可执行文件的格式ELF程序装载运行fork shell
1.3 内存保护
确保每个进程都有单独的内存空间。保证操作系统不受用户进程影响,用户进程不受其它用户进程影响。
内存保护可采取两种方法
- 在CPU中设置一对上、下限寄存器,存放用户作业在主存中的下限和上限地址。判断越界
- 采用重定位寄存器(基地址寄存器)、界地址寄存器(限长寄存器)。前者存放起始物理地址,后者存放逻辑地址的最大值
- 加载这俩寄存器必须使用特权指令,只有操作系统才能加载这俩存储器
【王道P168】
1.4 覆盖与交换
内存空间 扩充
- 覆盖(节约,时间上扩展)
- 交换(借用,空间上扩展)
- 虚拟存储技术
覆盖与交换技术是在多道程序环境下用来扩充内存的两种方法。解决在小内存空间运行大作业的问题
覆盖
- 把一个大的程序划分成一个固定区和一系列的覆盖,经常活跃的部分放在固定区,每个覆盖是一个相对独立的程序单位。把程序执行时并不要求同时装入主存的覆盖组成一组,称其为覆盖段(通常按调用关系分段),这个覆盖段被分配到同一个存储区域。这个存储区域称之为覆盖区,它与覆盖段一一对应。
- 缺点:程序设计时确定,不依靠操作系统判断覆盖段是什么(编程时必须划分程序模块和确定程序模块之间的覆盖关系)增加编程复杂度。从外存装入覆盖文件,以时间延长来换取空间节省。
交换
- 交换就是把暂时不用的某个(些)程序及其数据的部分或全部从主存移到辅存中去,腾出必要的存储空间;接着把指定程序或数据从辅存读到相应的主存中,并将控制转给它,让其在系统上运行
- 优点:增加并发运行的程序数目,并且给用户提供适当的响应时间;(操作系统支持交换)编写程序时不影响程序结构
- 缺点:对换入和换出的控制增加处理机开销;程序整个地址空间都进行传送,没有考虑执行过程中地址访问的统计特性
交换技术的几个问题
- 选择那个进程换出内存:等待IO的进程
- 何时发生交换
- 只要不用(或很少再用)就换出
- 只在内存空间不够或有不够的危险时换出
- 交换时需要做哪些工作
- 保存前一个进程的运行现场:寄存器、堆栈等
- 创建新进程的运行现场
- 换入回内存时位置的确定
覆盖与交换技术的区别
- 覆盖可减少一个程序运行所需的空间。交换可让整个程序暂存于外存中,让出内存空间。
- 覆盖是由程序员实现的,操作系统根据程序员提供的覆盖结构来完成程序段之间的覆盖。交换技术不要求程序员给出程序段之间的覆盖结构
- 覆盖技术主要对同一个作业或程序进行。交换主要在作业或程序间之间进行
1.5 分区管理——多道程序内存管理
了解:单道程序内存管理
空间的分配:分区式分配
- 把内存分为一些大小相等或不等的分区(partition)每个应用程序占用一个或几个分区。操作系统占用其中一个分区。
- 适用于多道程序系统和分时系统,支持多个程序并发执行,但难以进行内存分区的共享。
方法:
-
单一连续分配——有内碎片 无外碎片
- 分为系统区和用户区
- 单用户、单人舞的操作系统
-
固定分区分配——有内碎片 无外碎片
-
把内存划分为若干个固定大小的连续分区。
- 分区大小相等:只适合于多个相同程序的并发执行(处理多个类型相同的对象)。
- 分区大小不等:多个小分区、适量的中等分区、少量的大分区。根据程序的大小,分配当前空闲的、适当大小的分区
-
优点:易于实现,开销小
缺点:内碎片造成浪费,分区总数固定,限制了并发执行的程序数目;程序可能太大放不下
-
采用的数据结构:分区表——记录分区的大小、起址、状态(是否已被分配)
-
分配方式
- 单一队列分配:多个用户程序排在一个共同的队列里面等待分区分配
- 多队列分配:每个分区一个队列,程序按照大小排在相应的队列里
-
-
动态分区分配/可变分区分配——无内碎片 有外碎片
外部碎片才是造成内存系统性能下降的主要原因。外部碎片可以被整理后清除。
消除外部碎片的方法:紧凑技术
闲置空间的管理
- 位图表示法(分区表):
- 给每个分配单元赋予一个bit,用来记录该分配单元是否闲置。一般0是闲置,1是占用
- 空间成本固定:不依赖于内存中的程序数量。
- 时间成本低:操作简单,直接修改其位图值即可。
- 没有容错能力:如果一个分配单元为1,不能肯定应该为1还是因错误变成1。
- 链表表示法(分区链表):
- 将分配单元按照是否闲置链接起来
- 空间成本:取决于程序的数量。
- 时间成本:链表扫描通常速度较慢,还要进行链表项的插入、删除和修改。
- 有一定容错能力:因为链表有被占空间和闲置空间的表项,可以相互验证
内存分配采用两张表:已分配分区表和未分配分区表
动态分区分配算法
-
首次适应算法(First Fit)
-
空闲分区以地址递增的次序链接,每次从头开始找
-
内存的低地址部分出现很多小的空闲分区,而每次查找时都要经过这些分区,增加了开销
-
-
下次适应算法(Next Fit)
-
从上次查找结束的地方开始查找
-
特点:使存储空间的利用更加均衡,不致使小的空闲区集中在存储区的一端,但这会导致缺乏大的空闲分区
-
-
最佳适应算法(Best Fit)
-
空闲分区按容量递增的次序形成空闲分区链
-
往往使剩下的空闲区非常小,从而在存储器中留下许多难以利用的小空闲区(碎片)
-
-
最坏适应算法(Worst Fit)
-
空闲分区按容量递减的次序形成空闲分区链
-
最大的空闲分区总是因首先分配而划分,当有大作业到来时,其存储空间的申请往往会得不到满足
-
了解:
- 基于索引搜索的分配算法
- 伙伴系统
存储分配的三种方式
- 直接指定方式
- 编译程序对源程序进行汇编时所用的是实际地址
- eg:jal、jr
- 静态分配
- 编程时,可从地址空间的零地址开始
- 当装配程序对其进行连接装入时,才确定在主存中的地址
- 动态分配
- 作业在存储空间中的位置,在其装入时确定,在其执行过程中可根据需要申请附加的存储空间,而且一个作业已占用的部分区域不再需要时,可以要求归还给系统。