【BUAA-OS-理论课】3.1-存储管理基础

本文内容系2024年北航计算机学院/软件学院操作系统课程课堂笔记,内容大部分取自操作系统课程组PPT,少量来源于互联网,若有侵权请联系删除。文章内容如有错漏,敬请批评指正!


3.1 存储管理基础

3.1.1 程序的链接与加载

一、程序的链接与加载

1. 过程原理分析

一个程序本质上由bss段、data段、text段组成。

  • bss段(Block Started by Symbol):存放程序中未初始化的全局变量。bss段属于静态内存分配
  • data段(数据段):存放程序中已初始化的全局变量。数据段属于静态内存分配
  • text段(代码段):存放程序执行代码的一块内存区域。大小在程序运行前就已经确定,通常只读,也可能包含字符串常量等只读的常数变量。
(1)ELF文件格式

ELF(Executable and Linkable Format):可执行和链接格式
ELF

(2)链接

在这里插入图片描述

(3)加载

在这里插入图片描述

进程地址映射问题(以32位Linux为例)
在这里插入图片描述

进程的逻辑空间:内核虚存(是用户不可见的进程空间,由OS使用)+ 进程虚存(用户可见的进程逻辑空间:程序、数据、堆栈)

使用分段或分页实现加载

程序以段加载:代码段和数据段都在segment中,一个segment在文件中的大小小于等于其在内存中的大小。若“小于”,在载入内存时通过补零使其达到其在内存中应有的大小(lab1)

程序的装载流程:

  • 读取魔数(0x7f,E,L,F)以确认文件确实是ELF文件
  • 找到段表项(在头部给出信息找到每一个段表项)
  • 解析各个段应当被加载的虚地址、文件中的偏移、在内存中的大小和在文件中的大小
  • 对于每一个段,根据其在内存中的大小,为其分配足够的物理页,并映射到指定的虚地址上。再将文件中的内容拷贝到内存中。
  • 若MemSize > FileSize,用0填充
  • 设置进程控制块中的PC为ELF文件中记载的入口地址
  • 控制权交给进程开始执行

加载后,text和data段都在可执行文件中,从可执行文件中加载;而bss不在,由系统初始化

栈 (stack):存放、交换临时数据的内存区;堆(heap):存放进程运行中动态分配的内存段

2. C程序实例分析(MIPS)

gcc调用包含的工具: cc1 - 预处理器和编译器;as - 汇编器;collect2 - 链接器

(1)符号表和重定位表

用objdump反汇编ELF文件:偏移、机器码、汇编指令

函数调用在汇编文件里就是jal指令

(2)链接
  • 编译:.c -> .o
    编译时函数定义在不同文件,无法知道地址:

    • E 重定位目标文件
    • U 未解析符号
    • D 已定义符号
  • 链接的过程:将.o文件链接到一起,形成最终的可执行文件

    • 扫描各个目标文件,将之前未填写的地址写上,生成一个真正可执行的文件
  • 重定位:将之前未填写的地址填写的过程

(3)加载

执行程序的过程:

  • shell 调用fork()系统调用,创建出一个子进程(装载前)
  • 子进程调用 execve() 加载 program(装载工作)

实际的处理动作在do_execve()

地址空间:源程序经过编译后得到的目标程序,存在于它所限定的地址范围内。逻辑地址的集合——现代计算机中CPU访问内存所使用的地址

存储空间:主存中一系列存储信息的物理单元的集合。物理地址的集合

3.1.2 存储器硬件发展

存储器的发展方向:

  • 用户角度:高速、大容量和小体积。
  • 资源管理角度:为多用户提供服务,效率、利用率、能耗

在大容量方面的发展:接口标准、存储密度等

SRAM(静态):快,贵,容量小——构成高速缓存的基本存储器件

DRAM(动态):慢,集成度高,便宜,容量大

存储组织:在存储技术和 CPU 寻址技术许可的范围内组织合理的存储结构。其依据是访问速度匹配关系、容量要求和价格。

3.1.3 存储管理的目标

研究对象:以内存为中心的存储资源

用户角度(程序员):容量大;速度快(性能);独立拥有,不受干扰(安全)

资源管理角度:为多用户提供服务;效率、利用率、能耗

存储管理的基石:

  • 地址独立(程序发出的地址与物理地址无关)
  • 地址保护(一个程序不能访问另一个程序的地址空间)

存储管理要解决的问题:分配和回收

从内存管理的角度看,一个程序成功加载到内存,如果没有足够的内存可以分配,该程序也不一定能够成功运行。

3.1.4 存储器分配方法

存储分配三种方式:直接指定(用实际地址)、静态分配、动态分配

单道程序的内存管理

条件:此时,整个内存里只有2个程序:1个用户程序和操作系统,操作系统所占空间固定,因此用户程序永远从同一地方开始运行。

结论:用户程序的地址在运行之前可以计算。

方法:静态地址翻译,在程序运行之前就计算出所有物理地址,由加载器实现。

  • 优点:执行时无需地址翻译,程序运行速度快
  • 缺点:比物理内存大的程序无法加载,因而无法运行;小程序空间浪费,I/O时间长造成资源浪费

多道程序的内存管理

空间分配:分区(partition)式分配,每个应用程序占一个或多个分区。操作系统占用其中一个分区。

适用于多道程序系统和分时系统,支持多个程序并发执行,但难以进行内存分区的共享。

固定式分区

把内存划分为若干个固定大小的连续分区。——程序适应分区

  • 分区大小相等:只适合于多个相同程序的并发执行
  • 分区大小不等:多个小分区、适量中等分区、少量大分区。根据程序的大小,分配当前空闲的、适当大小的分区。

单一队列分配方式:当需要加载程序时,选择一个当前闲置且容量足够大的分区进行加载,可采用共享队列的固定分区(多个用户程序排在一个共同的队列里面等待分区)分配。

在这里插入图片描述

多队列分配方式:给每个分区一个队列,程序按照大小排在相应的队列里(以防一个小程序占用一个大分区,使得大程序无法加载)。

多队列

固定式分区管理,

  • 优点:易于实现,开销小

  • 缺点:内碎片造成浪费,分区总数固定,限制了并发执行的程序数目

  • 采用的数据结构:分区表——记录分区的大小和使用情况
    分区表

可变式分区

分区的边界可以移动,即分区的大小可变。——分区适应程序

  • 优点:没有内碎片
  • 缺点:有外碎片

跟踪内存(管理闲置空间)的办法:位图表示法(分区表)、链表表示法(分区链表)

  • 位图表示法:给每个分配单元赋予一个字位(0/1),用来记录该分配单元是否闲置。

    • 空间成本固定,时间成本低
    • 没有容错能力:若一个分配单元为1,不能肯定是1还是因错误变成1
  • 链表表示法:将分配单元按照是否闲置链接起来。

    • 空间成本取决于程序数量,时间成本高(链表增删改遍历)
    • 有一定容错:链表有被占空间和闲置空间的表项,可以相互验证
    • 内存分配采用两张表:已分配分区表和未分配分区表。

分配内存:

  • 事先规定 size 是不再切割的剩余分区的大小。
  • 设请求的分区大小为 u.size ,空闲分区的大小为m.size 。
  • 若 m.size-u.size≤size ,将整个分区分配给请求者。
  • 否则,从该分区中按请求的大小划分出一块内存空间分配出去,余下的部分仍留在空闲分区表/链中。
基于顺序搜索的匹配算法

一般只是适合于较小的系统

  1. 首次适应(First Fit):所有空白区按地址递增顺序连在一起,分配存储区域时从始端查找,选择第一个满足请求的空白块
    • 优点:分配和释放时间性能好,较大空闲分区保留在内存高端
    • 缺点:随着内存不断分配,会产生很多小分区,开销增大
  2. 下次适应(Next Fit):空白区构成循环链总是从上次查找结束的地方开始,找到满足要求的就划分出去。
    • 不致使小的空闲区集中在存储区的一端,但会导致缺乏大的空闲分区
  3. 最佳适应(Best Fit):容量递增次序排列,寻找最接近于作业要求的存储区域
    • 保留了大的空闲分区,但留下许多难以利用的小空闲区(碎片)
  4. 最坏适应(Worst Fit):容量递减次序排列,寻找最大的空白区
    • 分给作业后剩下的空闲分区较大,可装下其他作业;但大作业的存储空间申请往往得不到满足
  1. 内存分配和释放平均时间之和最大的是最佳适应算法
  2. 可变分区又称为动态分区,它是在系统运行过程中在作业装入动态建立的

回收空白分区时需要进行分区合并,系统开销大。

基于索引搜索的匹配算法

用于大中型系统

  • 快速适应算法(分类搜索法):空闲分区按容量大小分类常用长度设立单独空闲区链表,系统为多个空闲链表设立一张管理索引表

    • 优点:查找效率高,仅需要根据程序的长度,寻找到能容纳它的最小空闲区链表,取下第一块进行分配即可。保留大的分区,不会产生内存碎片
    • 缺点:分区归还主存时算法复杂,系统开销较大;一个分区只属于一个进程,浪费。空间换时间。
  • 伙伴系统(buddy system,Linux):介于固定分区和可变分区之间。分配存储块时将大的分裂成的两个等大小块,称为伙伴。

    并不是任意2个相同大小的内存块都称为“伙伴”

    • 大小均为2的k次幂,分配时向上取整次幂,找不到则分配更大的并分裂。
    • 内存回收的时候,首先考虑将被释放的块与其伙伴(如果空闲的话)合并成一个大的空闲块,合并后的块再与其伙伴合并,直至不能再合并
    • 速度快,但内部碎片严重。

伙伴系统

紧凑技术
  • 内部碎片:分配给作业的存储空间中未被利用的部分。无法被整理,已经被分配出去了,只是未被利用
  • 外部碎片:系统中无法利用的小的空闲分区,是内存系统性能下降的主要原因。消除方法:紧凑技术
  • 紧凑技术(Compaction):通过移动作业把多个分散的小分区拼接成一个大分区
    • 目标:消除外部碎片,使多个小空闲区连成大空闲区
    • 紧凑时机:找不到足够大的空闲分区且总空闲分区容量可以满足作业要求
    • 实现支撑:动态重定位,修改或变换作业地址
多重分区

多重分区分配:一个作业由相对独立的程序段和数据段组成,将这些片断分别装入到存储空间中不同的区域内的分配方式。

分区的存储保护:防止一个作业破坏操作系统或其他作业。方法:

  • 界限寄存器:上下界寄存器方法;基址、限长寄存器方法
  • 存储保护键(每个存储块上锁(保护键),每个作业给一把钥匙(同样赋予保护键),运行时检查是否匹配)

多道程序环境下,程序成型时可能需要更多空间,怎么办?——覆盖与交换,扩充内存

  • 覆盖(Overlay,早期):
    • 一个程序划分为一系列功能独立的程序段,执行时不要求同时装入内存的程序段组成一组覆盖段,共享主存的一个区域
    • 程序员要向系统指明覆盖结构对用户不透明,增加负担。

覆盖

  • 交换(Swapping,现代):把暂时不用的程序及其数据的部分或全部从主存移到辅存,腾出必要的存储空间;再把指定程序或数据从辅存读到相应的主存中,并将控制转给它,让其在系统上运行。
    • 优点:增加并发运行的程序数目,并且给用户提供适当的响应时间;编写程序时不影响程序结构
    • 缺点:对换入和换出的控制增加处理机开销;程序整个地址空间都进行传送,没有考虑执行过程中地址访问的统计特性。

覆盖与交换的区别:

覆盖交换
大作业,小内存多作业,小内存
减少一个程序运行所需空间让整个程序暂存于外存,让出内存空间
由程序员实现,操作系统据此完成程序段之间的覆盖不要求程序员给出程序段之间的覆盖结构。对程序员透明
主要对同一作业或程序进行主要在作业或程序之间进行
  • 29
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值