880 likes | 1.04k Views
第四章 存储器管理. 今天虽然主存价格已相当便宜,但主存容量仍然是计算机四大硬件资源中最关键而又最紧张的“ 瓶颈”资源。因此存储器仍然是一种宝贵而有紧俏的资源,对主存的管理和有效使用仍然是今天操作系统十分重要的内容。. 三国志游戏系列. 这说明: 程序规模的增长速度远远大于存储器容量的 增长速度。 Parkinson 定律: 存储器有多大,程序有多长。. 高速缓存. n+k ~ 几百 k. cpu 可访. 主存. nM ~ 几百 M. 外存. n+M~nG(G=1kn). 关于地址 物理地址 是主存的真实地址 ––– 绝对地址
E N D
第四章 存储器管理 今天虽然主存价格已相当便宜,但主存容量仍然是计算机四大硬件资源中最关键而又最紧张的“ 瓶颈”资源。因此存储器仍然是一种宝贵而有紧俏的资源,对主存的管理和有效使用仍然是今天操作系统十分重要的内容。
三国志游戏系列 这说明: 程序规模的增长速度远远大于存储器容量的增长速度。 Parkinson定律: 存储器有多大,程序有多长。
高速缓存 n+k ~ 几百k cpu可访 主存 nM ~ 几百M 外存 n+M~nG(G=1kn)
关于地址 物理地址是主存的真实地址 ––– 绝对地址 它是:存储控制部件能够识别的主存单元编号(或字节地址)。 逻辑地址:又称相对地址,是指相对于某个基准量(通常用0)编址时所使用的地址,相对地址常用于程序编写和编译过程中。 名空间––– 由程序员所写符号组成。 地址空间––– 一个目标程序所限定的地址集合。 存贮空间–––物理地址的集合间
4.1.1 程序的装入和链接 内存 目标模块 编译 源程序 链接 程序 装入 程序 装入模块 ….. 库
4.1.1 程序的装入 • 程序的装入 • 将一个模块装入内存时,可采用三种方式: 绝对装入方式 可重定位方式 动态运行时装入方式
1.绝对装入方式 按照装入模块中的地址,将程序和数据装入内存。装入模块 被装入内存后,由于程序中的逻辑地址与实际内存地址完全 相同,故不须对程序和数据的地址进行修改。 2.可重定位装入方式(静态重定位) 装入模块装入内存后,装入模块中的所有逻辑地址与实际装 入内存的物理地址不同。通常把装入时对目标程序中指令和 数据的修改过程称为重定位。通常地址变换一次完成,以后 不再改变,故称为静态重定位。 3.动态运行时装入(动态重定位) 装入模块装入内存后,并不立即把装入模块中的相对地址转 换为绝对地址,直到程序真正执行时才进行。装入内存后, 所有地址仍是相对地址。
物理地址空间 逻辑地址空间 . . . . 1000 0 . . . . . 1100 100 str 5 [200]ldr R1, [200]add R2,R1,3str R2, [204] str 5 [200]ldr R1, [200]add R2,R1,3str R2, [204] 装入 分区 编译 链接 1200 x 200 x 1204 y 204 y 1300 300 . . . 源程序 int x, y; x = 5; y = x + 3;
物理地址空间 逻辑地址空间 . . 1000 . . 0 . . . . . 1100 str 5 [1200]ldr R1,[1200]add R2,R1,3str R2,[1204] 100 str 5 [200]ldr R1, [200]add R2,R1,3str R2, [204] 装入分区 1200 x 200 x 1204 y 204 y 1300 300 . . .
物理地址空间 逻辑地址空间 . . . . 1000 0 . . . . . 1100 100 str 5 [200]ldr R1, [200]add R2,R1,3str R2, [204] str 5 [200]ldr R1, [200]add R2,R1,3str R2, [204] 装入 分区 1200 x 200 x 1204 y 204 y 1300 300 . . . 基地址寄存器 1000 相对地址 + 200
4.1.2 程序的链接 • 链接程序的功能,是将经过编译或汇编所得到的一组目标模块以及它们所需要的库函数,装配成一个完整的装入模块。 • 实现链接的方法 • 静态链接 • 装入时动态链接 • 运行时动态链接
1、静态链接方式 0 0 模块A CALL B; Return; 模块A JSR’L’; Return; L-1 L-1 0 L 模块B JSR’L+M’; Return; 模块B CALL C; Return; L+M-1 M-1 L+M 模块C Return; 0 模块C Return; L+M+N-1 N-1 需要解决的两个问题: 1、对相对地址进行修改;2、变换外部调用符号。
2、装入时动态链接: 用户源程序经编译后所得到的目标模块,是在装 入内存时,边装入边链接的。 优点: 1、便于软件版本的修改和更新。 2、便于实现。 3、运行时动态链接(Run-Time Dynamic Linking) 是近几年流行起来的运行时动态链接方式。这种链接方式,可将某些目标模块的链接,推迟到执行时才进行。
4.2 连续分配方式 • 单一连续分配 • 固定分区分配 • 动态分区分配 • 动态重定位分区分配
o.s区 用户区 4.2.1 单一连续分配 概要:存区分为o.s连续区和用户连续区 单用户o.s的内存管理十分 简单,因为存贮器在任何时 候都只保存一个用户进程, 除o.s本身占据的内存外都 可分配给用户使用。 受保护
方案: o.s可以占据RAM的底部(a)或顶部(b) 也可以部分在内存顶部的Rom中,另一部分存放RAM底部(c)
用户程序 位于RAM中的 操作系统 位于RAM中的 操作系统 用户程序 ROM中的 设备驱动程序 用户程序 位于RAM中的 操作系统 0xFFF... 0 0 0
4.2.2 固定分区分配 • 预先把可分配的内存空间分割成若干个连续区域,每一区域称为分区。每个分区的大小可以相同也可以不同,分区大小固定不变,每个分区装一个且只能装一个作业 • 1、划分分区的方法: • 分区大小相等 • 作业太大,太小都有问题 • 分区大小不等 • 2、内存分配 • 使用分区使用表
0区 o.s区 20k 区号 大小 起址 状态 1区 1 8k in using 20k 28k 2 32k 28k NuL 2区 60k 3 68k 60k in using 90k 3区 4 128k 128k NuL 128k 4区 256k (存贮分块表MBT)
4.2.3 动态分区分配 • 动态分区分配是根据进程的实际需要,动态地为之分配连续的内存空间。解决三个问题 • 1、分区分配的数据结构 • (1)空闲分区表 • 用于为内存中每个尚未分配出去的分区设置一个表项,每个分区的表项包含分区序号、分区始址及分区大小等表目。 • (2)空闲分区链 • 为了实现对空闲分区的分配和链接,在每个分区的起始部分,设置一些用于控制分区分配的信息,以及用于链接各分区的前向指针;再分区尾部则设置一后向指针;然后,通过前、后向指针将所有的分区链接成一个双向链。
前向 指针 N个字节可用 后向 指针 N+2 N+2 0 0 空闲链结构
指针 10k 60k 90k 20k • 2、分区分配算法 • (1)首次适应算法:(FF) • 将空白区按存贮顺序链成一个队列,用一指针指向队首分配时将找到的第一个满足要求的空白区分配给它。 有四块空白区(从低地址高地址),来了一个作业需分配19k内存。
指针 10k 60k 90k 20k 41k 解: FF特点: 在高地址空白区中保持较大空白区(每次从10k开始分配寻找)。
1 2 指针移动 (2) 循环首次适应(Next fit: NF) 将空白区组成环状队列,按循环顺序寻找空白区。(与FF区别,头指针从低地址开始向高地址循环移动) NF特点: 使得小空白区均匀分布,易于与其它空白区合并。
指针 10k 60k 90k 20k (3) 最佳适应算法(Best fit: BF) 将空白区按大小排成队列,寻找时总是以最小的空白区开始,找到第一个合适的分区 例: 来一个19k的作业
指针 10k 20k 60k 90k 1k 解: 特点: 最佳地利用分区; 开销比较大,并不是最好算法。
3、分区分配操作 • (1)分配内存 • 首先,系统要利用某种分配算法,从空闲分区链(表)中找到所需的分区,设请求的分区大小为u.size,表中每个空闲分区的大小可表示为m.size。若m.size-u.size<=size(size是事先规定的不再切割的剩余分区的大小),说明多余部分太小,可不再切割,将整个分区分给请求者;否则,从该分区中化除与请求的大小相等的内存分配出去,余下的部分仍留再空闲分区链或空闲分区表中。然后,将分配区的首址返回给调用者。
从头开始查表 Y 检查完否? 返回 N N m.size>u.size? 继续检索下一个表项 Y Y m.size-u.size<=size? N 从该分区中划出 u.size大小的分区 将该分区从链中移出 将该分区分配给请求 者修改有关数据结构 返回
3、分区分配操作 • (2)回收内存 • 当某一块归还后,前后空间合并,修改内存空闲块表 • 考虑:上邻、下邻、上下相邻、上下不相邻 F1 F1 回收区 回收区 回收区 F2 F2
4.2.4 可重定位分区分配 Job1 Job1 • 1、动态重定位的引入 • 碎片(零头)问题:存在于已分配的分区之间的一些不能充分利用的空白区 • 紧凑技术:通过在内存移动程序,将所有小的空闲区域合并为大的空闲区域 Job2 Job3 Job2 Job3 Job4
0 10000 相对地址 重定位寄存器 10100 Load 1,2500 2500 10000 Load 1,2500 ≈ ≈ ≈ ≈ 12500 + 365 365 15000 作业J 处理机一侧 存储器一侧 主存 动态重定位示意 • 2、动态重定位的实现 100 2500 5000
请求分配 u.size分区 三、动态重定位分区分配算法: 简缩空闲分区链(表) N 找到大于 u.size的可 用区否? N 无法分配 返回 空闲分区总 和>=u.size Y Y 进行紧凑形成 连续空闲区 动态分区分配 修改有关的 数据结构 修改有关的 数据结构 返回分区号 及首址 动态分区分配算法流程
4.2.5 对换(Swapping) • 1.对换的引入 • 内存中某些进程,等待事件发生而被阻塞,占用了大量内存空间 • 许多作业在外存等待,因无内存无法进入内存运行 • 对换技术被广泛地运用于早期的小型分时系统的存贮管理中。其目的,一方面解决主存容量不够大的矛盾,一方面使各分时用户能保证合理的响应时间。所谓交换,就是系统根据需要把主存中暂时不运行的某个(或某些)作业部分或全部移到外存,而把外存中的某个(或某些)作业移到相应的主存区,并使其投入运行。 • 包括“进程对换”,“页面对换”,“分段对换”
2、对换空间的管理 • 通常把外存分为文件区和对换区。 • 文件区:存放文件,需要提高文件存储空间利用率,离散分配方式 • 对换区:用于存放从内存换出的进程,需要提高进程换入和换出的速度,连续分配方式 • 对外存空闲盘块管理:空闲分区表,空闲分区链 • 分配算法与分配过程同其他连续分配方式
3、进程的换出与换入 • 进程的换出 • 选择处于阻塞状态且优先级 • 将进程的程序和数据传送到磁盘对换区 • 若传送未出错,回收内存,修改PCB • 进程的换入 • 选择换出时间最长的“就绪”进程 • 换入 • 直到无可换入或换出的进程
4.3 基本分页存储管理方式 • 分页存储管理是解决存储碎片的一种方法。 动态重定位是解决存储器碎片问题的一种途径,但要移动大量信息花去不少处理机时间,代价比较高,这是因为这种分配要求把作业必须安置在一连续存储区内的缘故,而分页存储管理正是要避开这种连续性要求。
4.3.1 页面与页表 • 1.页面 • 页面和物理块 • 把用户程序按逻辑页划分成大小相等的部分,称为页。从0开始编制页号,页内地址是相对于0编址。内存空间 按页的大小划分为大小相等的区域,称为内存块(物理页面,页框) • 页面大小 • 512B~8KB
31 12 0 11 页 号 P 位移量W • 2.地址结构 页内地址 • 若给定一个逻辑地址空间中的地址为A,页面大小为L,则页号P和页内地址w可按下式求得: P=INT[A/L] W=[A] MOD L 其中,INT是整除函数, MOD是取余函数。
页框 (物理块) . . 页号 . . 0 . 0 1 2 1 . . . 3 2 . 4 3 4 . 5 5 6 6 作业的 地址空间 页表 主存中页框(物理块) • 2.页表 • 系统为每个进程建立一个页表,页表给出逻辑页号和具体内存块号相应的关系
4.3.2 地址变换机构 • 1、基本的地址变换机构 • 页表寄存器PTR,存放当前进程的页表在内存的起始地址和长度 • 当进程要访问某个逻辑地址中的数据时,分页地址变换机构会自动地将有效地址分为页号和页内地址两部分,再以页号为索引取检索页表。查找操作由硬件执行,在检索之前,将页号与页表长度比较,若页号大于页表长度,则产生越界中断。若未出现越界错误,则将页表始址与页号和页表项长度的乘积相加,便得到该表项在页表中的位置,于是可从中得到该页的物理块号,将之装入物理地址寄存器,与此同时,再将有效地址寄存器中的页内地址直接送入物理地址寄存器的块内地址字段中,这样便完成了从逻辑地址到物理地址的变换。
越界中断 页表寄存器 逻辑地址L 页表始址 页表长度 > 页号(3) 页内地址 + 块 位移量 … … 物理地址 页表 分页系统的地址变换机构
2、具有快表的地址变换机构 从上述地址转换过程可以看出,执行一次访内操作至少要访 问主存两次。一次访页表,以确定所取数据或指令的物理地 址;另一次是根据地址取数据或指令。这样就把程序的执行 速度降低一倍。为了提高存取速度,通常设置一个专用的高 速缓冲寄存器组,用来存放页表的一部分。我们把存放在高 速缓冲寄存器中的页表叫快表,这个高速缓冲寄存器又叫联 想存贮器。
带有TLB的页式地址映射 先 后 (本图摘自Silberschatz, Galvin and Gagne: “Operating System Concepts”)
4.3.3两级和多级页表 • 而Windows NT 等使用x86的CPU的32位地址,使用4KB的页面(212),这意味着进程最多可以使用多达220(100多万)个页面。如果每个页表表目占4byte,那么每个进程的页表所占的空间是222byte,占去主存的1‰的空间,显然这样大的页表是不能全放在主存中的。为此对页表本身也采取分页措施。即把页表本身按固定大小分成为一个个页面(页面大小为 212=4KB)。
…… 页表大小 4K 页表大小 4K 页表大小 4K …… …… …… 例如某进程使用40M内存,页面大小为4K,页表项大小4字节 页表大小 40K 外部页表 4K 页面数为10K
每个小页表形成的页面中可以有210=1K个页表表目(每个表目4byte),共有210=1K个小页表。为了对1K个小页表进行管理和索引查找,设置一个页表目录,又称之为顶级页表,该顶级页表包含有1K个表目项,分别指出每个次级小页表所在物理页号和其他有关状态信息。这样,每个进程有一个页目录,它的每个表目映射一个页表。页目录是一级表,而每个小页表本身就是二级页表。每个小页表形成的页面中可以有210=1K个页表表目(每个表目4byte),共有210=1K个小页表。为了对1K个小页表进行管理和索引查找,设置一个页表目录,又称之为顶级页表,该顶级页表包含有1K个表目项,分别指出每个次级小页表所在物理页号和其他有关状态信息。这样,每个进程有一个页目录,它的每个表目映射一个页表。页目录是一级表,而每个小页表本身就是二级页表。 外层页号 外层页内地址 页内地址 p1 p2 d
外层页号 外层页内地址 页内地址 p1 p2 d b d 外部页表寄存器 + + 物理地址 页表 外部页表 为了地址变换实现上的方便,在地址机构中同样需要设置 一个外层页表寄存器,用于存放外层页表的始址,并利用 逻辑地址中的外层页号,作为外层页表的索引,从中找到 指定页表分页的首址,再利用p2作为指定页表分页的索引, 找到指定的页表项。其中即含有该页在内的物理块号,用 该块号和页内地址d即可构成访问内存的物理地址。
二级页表使用离散分配空间的方法解决了大页表需要大块二级页表使用离散分配空间的方法解决了大页表需要大块 连续空间存储的问题。但是页表占用的空间依然未减少。 解决用较少的内存空间去存放大页表的问题——将当前需 要的部分页表项调入内存,其余的页表项仍驻留在磁盘上, 需要时,再将它们调入内存。 ——虚拟内存 2.多级页表 通过二级页表的地址映射访问主存存取数据需要三次访问 主存(一次页目录,一次页表,最后是数据所在物理地址) ,所需时间是原来的三倍。当然对64位的地址,也可组织 成三级、四级页表,但性能的影响是不可忽视的。
4.4基本分段存储管理方式 • 固定分区->动态分区->分页存储,解决的是内存利用率的问题 • 分段存储解决的是用户对于编程和使用上多方面的要求。 • 4.4.1 分段存储管理方式的引入 • 页式存储管理(和分区存储管理)只有一个逻辑地址空间,即一维的线性连续空间,从0 到某个最大的逻辑地址。但是从程序员的角度来说,一个程序是由一组模块(片段)所组成的,每个片段是一个逻辑单元,如:主程序、函数、全局变量、栈、符号表等。为了体现这些逻辑单元的独立性,便于它们的共享、保护和修改,人们提出了段式存储管理的方法。