存储器管理
1 存储器的层次结构
计算机执行时,几乎每条指令都涉及对存储器的访问。因此要求对存储器的访问速度跟得上处理机的运行速度。考虑到价格和现实因素,如今的计算机大都采用了多层结构的存储器系统
1.1 存储器的多层结构
存储层次至少应具有三级:最高层为CPU寄存器、中间为主存、最底层为辅存
从上到下:①访问的速度越来越慢 ② 空间容量越来越大 ③单位价格越来越低
CPU 寄存器和主存又被称为可执行存储器,其中的信息在掉电后不复存在。但是辅存中的信息可以长期保存。
对于可执行存储器和辅存,计算机访问的机制是不同的。程序需要从辅存中载入可执行存储器才可以执行,访问辅存的时间远大于访问可执行存储器的时间。
1.2 主存储器与寄存器
(1)主存储器
简称内存或主存,用于保存进程运行时的程序和数据。
通常处理机都是从主存储器中取得指令和数据的,并将其所得的指令放入指令寄存器,而将其所读取的数据装入到数据寄存器中。或者反之,将寄存器中的数据存入到主存储器。
主存的访问速度虽然也很快,但是还不够匹配 CPU 执行指令的速度,因此在计算机系统中引入了寄存器和高速缓冲存储器(Cache)
(2)寄存器
寄存器具有与处理机相同的速度,故对寄存器的访问速度最快,完全能与 CPU 协调工作,价格昂贵,容量小
1.3 高速缓存和磁盘缓存
(1)高速缓存
高速缓冲存储器介于寄存器和存储器之间,主要用于备份主存中常用的数据,以减少处理机对主存储器的访问次数,大幅提高程序执行速度。高速缓存的容量远大于寄存器。
查看性能,高速缓存通常分为多级结构,高到低
- 访问速度越来越低
- 容量越来越大
(2)磁盘缓存
为了缓和磁盘与主存的访问速度差异,设置了磁盘缓存,用于暂时存放频繁使用的一部分磁盘数据和信息,减少访问磁盘的次数。不是实际存在,而是利用主存中的部分存储空间存放磁盘中的信息。
2 程序的装入和链接
用户源程序在系统中运行,必须先将其装入内存,然后转变为一个可执行程序
步骤:
① 编译:由编译器(Compiler)对用户源程序进行编译,形成若干个目标模块(Object Module)
② 链接:由链接程序(Linker)将目标模块以及其所需要的目标函数链接在一起,形成一个完整的装入模块(Load Module)
③ 装入:由装入程序(Loader)将装入模块装入内存
2.1 地址以及映射
(1)逻辑地址 / 相对地址 / 虚地址
用户程序经过汇编或编译后形成目标代码,目标代码通常采用相对地址的形式
参照计算机组成原理:首地址记为 0,其余指令的地址都相对于首地址来进行编址,称为相对地址
相对地址的集合称为相对地址空间,也简称地址空间。
(2)物理地址 / 绝对地址 / 实地址
内存中存储单元的实际地址,可以直接寻址
内存单元的集合称为存储空间或绝对地址空间
(3)地址映射 / 重定位
当程序装入内存时, 操作系统要为该程序分配一个合适的内存空间,由于程序的逻辑地址与分配到内存物理地址不一致, 而 CPU 执行指令时,是按物理地址进行的,所以要进行地址转换。
2.2 程序的装入
在将一个装入模块装入内存的时候,有三种装入方式
(1)绝对装入方式—适用于单道程序环境
如果计算机系统很小,仅能运行单道程序,完全可以事先知道程序将存入内存的什么位置。此时编译过程中可以直接产生绝对地址的目标代码,不需要对程序和数据的地址进行修改。
优点:装入过程简单
缺点:不适用多道程序系统
(2)可重定位装入方式—适用于多道程序环境
在多道程序的环境下,编译程序不可能预知目标模块放入内存的地址,因此编译后形成的若干个目标模块的起始地址通常都是 0。
装入程序会将模块中的相对地址与程序在内存中的起始地址相加,得到程序的物理地址再装入程序。
这种方法通常在装入程序后便不再对程序的地址进行修改,因此也称为静态重定位方式
优点:不适用多道程序系统,无需硬件支持
缺点:不允许程序运行时在内存中移动位置
(3)动态运行时的装入方式
解决静态重定位方式的缺点,无法不允许程序在运行时移动位置。
动态运行时的装入程序在把装入模块装入内存后,并不立即把装入模块中的逻辑地址转换为物理地址,而是把这种地址转换推迟到程序真正要执行时才进行。装入内存后的所有地址都仍是逻辑地址。为使地址转换不影响指令的执行速度,这种方式需要一个重定位寄存器的支持。
优点:允许程序运行时在内存中移动位置
缺点:需要硬件支持
2.3 程序的链接
源程序经过编译后,可得到一组目标模块。链接程序将这组目标模块以及它们所需要的库函数装配成一个完整的装入模块,并且将个目标模块中的相对地址和外部调用符号转换成装入模块中的相对地址。
根据进行链接时间的不同,可以把链接分为以下三种L
(1)静态链接方式
在程序运行之前,先将各目标模块以及它们所需的库函数链接成一个完整的装配模块,以后便不再拆开
要解决两个问题:
- 对相对地址进行修改
- 变换外部调用符号
(2)装入时动态链接
优点:① 便于修改和更新 ② 便于实现对目标模块的共享
链接在装入时进行,即在装入一个目标时,若发生一个外部模块的调用事件,则由装入程序去找出相应的外部模块,将它装入内存,并把它链接到调用者模块上。在装入或运行时进行链接。通常被链接的共享代码称为动态链接库(DLL,Dynamic-Link Library)或共享库(shared library)
(3)运行时动态链接
链接在运行时进行,即在执行过程中,当发现一个被调用模块还没装入内存时,立即由 OS 找出该模块,将它装入内存,并把它链接到调用者模块上。在执行过程中未被用到的目标模块,都不会被调入内存和链接。
优点:加快程序的装入过程,节省内存空间
3 连续分配存储管理方式
3.1 单一连续分配
在早期的单道程序环境下,存储器管理将内存分为两个部分:
①系统区:仅供OS使用,通常放在内存的低址部分
② 内存区:系统区以外的全部内存空间, 提供给用户使用。仅装有一道用户程序。
3.2 固定分区分配
将用户空间划分为若干个固定大小的区域,在每个分区中只装入一道作业。这样使得能在内存中装入多道程序,并且程序之间互不干扰,可以并发运行。
(1)划分分区的方法
- 分区大小相等
缺点:缺乏灵活性
① 程序太小时,会造成空间浪费
② 程序太大时,无法装入程序
- 分区大小不等
划分方式:
① 多个小分区
② 适量的中等分区
③ 少量的大分区
优点:根据程序大小划分区域,增加存储器的分配灵活性
(2)内存分配
为了方便内存分配,通常将分区按期大小进行排队,并为之建立一张分区使用表,如图所示
3.3 动态分区分配
根据进程的实际需要,动态地为之分配内存空间,涉及三个方面的问题
(1)动态分区分配中的数据结构
常用有以下两种形式:
① 空闲分区表
② 空闲分区链(更常用)
(2)动态分区分配算法
(3)分区分配操作
主要操作是分配内存和回收内存
① 分配内存
设请求的分区大小为 u.size,表中每个空闲分区的大小可表示为 m.size
- 若 m.size-u.size ≤ size(size 是事先规定的不再切割的剩余分区的大小),说明多余部分太小,可不再切割,将整个分区分配给请求者
- 否则(即多余部分超过 size),便从该分区中按请求的大小划分出一块内存空间分配出去,余下的部分仍留在空闲分区链(表)中。然后,将分配区的首址返回给调用者
内存分配流程:
② 回收内存
根据回收区的首地址,从空闲区链中找到相应的插入点,根据回收部分尽可能大的原则,对下列四种情况分别作出不同操作
- 回收区与插入点的前一个空闲分区 F1 邻接。此时将二者合并,修改 F1 的大小,不为回收区分配新表项
- 回收区与插入点的后一个空闲分区 F2 邻接。此时将二者合并,使用回收区的首地址作为新空闲区的首地址,大小为二者之和
- 回收区同时与插入点的前、后两个分区 F1、F2 邻接。此时将三者合并,使用 F1 的首地址,大小为三者之和
- 回收区前后没有空闲分区。此时为回收区单独建立一个新表项,填写回收区的首地址和大小,插入空闲链中
3.4 基于顺序搜索的动态分区分配算法—适用不太大的系统
为了实现动态分区分配,通常是将系统中的空闲分区链接成一个链。所谓顺序搜索,是指依次搜索空闲分区链上的空闲分区,去寻找一个其大小能满足要求的分区
(1)首次适应算法(first fit,FF)
要求空闲分区链以地址递增的次序连接
每次从链首开始顺序查找,直到找到一个大小满足要求的空闲分区,将其分配给进程
优点:保留了高址部分的大空闲区,大作业可以得到分配
缺点:低址部分不断被分配,留下许多难以被利用的。很小的空闲分区(碎片)
(2)循环首次适应算法(next fit,NF)
要求将空闲区链形成一个环形链
类似顺序查找方式,但不是每次从链首开始查找,而是从上一次查找的空闲分区后面开始查找
优点:减少了查找空闲分区时的开销
缺点:使内存中的空闲分区分布均匀,缺乏大的空闲分区,大作业难以被分配
(3)最佳适应算法(best fit,BF)
要求将所有的空闲分区按照容量从小到大的顺序依次排列
优点:每次为作业分配内存时,总是把能满足要求的最小空闲分区分配给它
缺点:留下许多难以利用的碎片
(4)最坏适应算法(worst fit,WF)
要求将所有的空闲分区按照容量从大到小的顺序依次排列
优点:剩下空闲区不会太小,对中小作业有利;产生碎片的可能性最小;查找效率高,只看第一个区是否满足既可
缺点:缺乏大的空闲分区
3.5 基于索引搜索的动态分区分配算法—中大型系统往往会采用此类算法
(1)快速适应算法(quick fit)
将空闲分区根据容量大小进行分类,对每一类相同容量的所有空闲分区单独设立空闲分区链表,同时内存中设立一章管理索引表,记录每一种空闲分区的链表头指针,来管理各种不同类型的空闲分区。
步骤:①先从索引表中找到能容纳进程的最小空闲区链表 ② 从该链表中取下第一块进行分配,不对空闲区进行分割
优点:能保留大的分区;不产生内存碎片;查找效率高;
缺点:算法复杂,系统开销大;一个区属于一个进程,会造成一定的空间浪费
(2)伙伴系统(buddy system)
在系统运行过程中,会不断地划分空闲分区,按照大小进行分类,对相同大小的所有空闲分区单独设立一个空闲分区双向链表。因此共有 k 个空闲分区链表
分配过程:
① 首先找到一个满足条件的最小的 i,使得 2i-1 < n ≤ 2i(n 为进程所需空间大小)
② 查找空闲分区大小为 2i 的链表,若找到,则直接分配
③ 若未找到,则查找空闲分区大小为 2i+1 的链表,若找到,则将其分为两个大小相等的连续空间,其中一个用于分配,另一个加入空闲分区大小为 2i 的链表中。这一对空闲分区称为“伙伴”
④ 若未找到,则查找空闲分区大小为 2i+2 的链表,若找到,则将其分为两个大小相等的连续空间,其中一个用于分配,另一个加入空闲分区大小为 2i+1 的链表中。再将用于分配的一个空闲分区继续划分,其中一个用于分配,另一个加入空闲分区大小为 2i 的链表中
⑤ 以此类推
⑥ 最坏情况下,可能需要对 2k 的空闲分区进行 k 次分割才能得到所需分区
回收过程:
① 回收大小为 2i 的空闲分区时,若已存在其伙伴,则合并为大小为 2i+1 的空闲分区
② 若新空闲分区的伙伴已存在,则再次合并为大小为 2i+2 的空闲分区
③ 以此类推
④ 合并时,伙伴一定是相邻的,因此合并后得到的新空闲分区一定是连续的
对于一个大小为 2k,地址为 x 的内存块,其伙伴块的地址:
优点:减少小的空闲分区,提高了空闲分区的可使用率
缺点:分配和回收的时间长,时间性能比快速适应法差,但比顺序搜索算法好
(3)哈希算法
利用哈希快速查找的优点,以及空闲分区在可利用空闲区表中的分布规律,建立哈希函数,构造一张一空闲分区大小为关键字的哈希表,该表的每一个表项记录了一个对应的空闲分区链表。分配时,根据所需空闲分区大小,通过哈希函数计算,即得到在哈希表中的位置,从而得到相应的空闲分区链表
优点:没有内碎片
缺点:存在外碎片;如果大小不是任意的,也可能出现内碎片
3.6 动态可重定位分区分配
(1)紧凑
为了解决“外部碎片”的问题,将内存中的所有作业进行移动,从而将分散的多个空闲分区移到同一端拼接成一个大的空闲分区。
缺点:在每次“紧凑”后,都必须对移动了的程序或数据进行重定位,大大影响系统的效率。
(2)解决方法—动态重定位
动态运行时装入的方式中,作业装入内存后的所有地址仍然都是相对(逻辑)地址,相对地址转换为绝对(物理)地址的工作被推迟到程序指令要真正执行时进行。为使地址的转换不会影响到指令的执行速度,必须有硬件地址变换机构的支持,即须在系统中增设一个重定位寄存器,用它来存放程序(数据)在内存中的起始地址。程序在执行时,真正访问的内存地址是相对地址与重定位寄存器中的地址相加而形成的
地址的变换过程是在程序执行期间,随着对每条指令或数据的访问自动进行的,故称为动态重定位。当系统对内存进行了“紧凑”,而使若干程序从内存的某处移至另一处时,不需对程序做任何修改,只要用该程序在内存的新起始地址去置换原来的起始地址即可
(3)动态重定位分区分配算法
动态重定位分区分配算法与动态分区分配算法基本上相同,
差别仅在于:在这种分配算法中,增加了紧凑的功能
3.7 分区的保护
在连续分配方式中,为了防止一个用户作业破坏 OS 或其他用户的作业,常采用界限寄存器或保护键的方法来进行分区的保护
(1)界限寄存器
每当进行内存访问时,硬件自动将所访问的内存地址与界限寄存器的值进行比较,若发生地址越界,则产生越界中断、
(2)保护键
它为每个分区分配一个独立的保护键,相当于一个锁;同时为每个进程分配一个相应的钥匙。当进行内存访问时,都要检查钥匙和被访问单元的锁是否匹配,若不匹配,则发生保护性中断。
4 对换
最早的技术:系统把所有的用户作业存放在磁盘上,每次只能调入一个作业进入内存,当该作业的一个时间片用完时,将它调至外存的后备队列上等待,再从后备队列上将另一个作业调入内存。
4.1 对换的引入
多个程序并发执行,可以将暂时不能执行的程序送到外存中,从而获得空闲内存空间来装入新程序,或读入保存在外存中而目前到达就绪状态的进程。交换单位可以为整个进程的地址空间(进程对换),也可以为进程的部分地址空间(页面对换/分段对换)
4.2 对换的类型
每次对换都是将一定数量的程序或数据换入或换出内存。根据每次对换时所对换的数量,可将对换分成如下两类:
(1)整体对换
处理机中级调度实际上就是存储器的对换功能,目的是解决内存紧张问题,提高内存的利用率和系统的吞吐量。中级调度中对换是以整个进程为单位,故称之为”进程对换”or”整体对换”
(2)页面(分段)对换
对换以进程的一个”页面”or”分段”为单位进行,目的是支持虚拟存储系统。
系统必须能实现三方面的功能:① 对对换空间的管理 ② 进程的换出 ③ 进程的换入
4.3 对换原理
换出:暂停执行内存中的进程,将整个进程的地址空间保存到外存的交换区中
换入:将外存中由阻塞变为就绪的进程的地址空间读入到内存中,并将该进程送到就绪队列
4.4 对换空间的管理
(1)对换空间管理的主要目标
- 对文件区管理的主要目标
文件区占磁盘空间的大部分。由于通常的文件都是较长时间驻留在外存上,对它的访问效率是较低的,所以文件区管理的主要目标是提高文件存储空间的利用率。采用离散分配方式。
- 对对换空间管理的主要目标
对换空间占磁盘空间的小部分,用于存放内存换出的进程。由于这些进程在对换区中驻留的空间是短暂,而对换操作的频率却较高,所以主要目标是提高进程换入和换出的速度。采用连续分配方式。
(2)对换区空间盘块管理中的数据结构
空闲分区表或者空闲分区链
空闲分区表包含两项:① 对换区的首地址及其大小 ② 分别用盘块号和盘块数表示
(3)对换空间的分配与回收
对换区的回收(四种情况):
- 回收分区与插入点的前一个空闲分区F1相邻接
- 回收分区与插入点的后一个空闲分区F2相邻接
- 回收分区同时与插入点的前、后两个分区邻接
- 收回分区既不与F1邻接,又不与F2邻接
4.5 进程的换出和换入
(1)进程的换出
将内存中的某些进程调出至对换区,空出内存空间
步骤:
① 选择被换出的进程。
首先选择处于阻塞状态或睡眠状态的进程。如果有多个这样的进程时,应该选择优先级最低的进程。
如果系统无阻塞进程,而现在的内存空间不足与满足需要,便选择优先级最低的就绪进程换出。
② 进程换出过程
只能换出非共享的程序和数据段。
- 申请对换空间
- 若申请成功,启动磁盘,将该进程的程序和数据传送到磁盘的对换区上。
- 若传送过程未出现错误,便回收该进程所占用的内存空间
- 对该进程的进程控制块和内存分配表等数据结构做相应的修改。
- 若此时内存中还有可换出的进程,则继续执行换出进程,直到内存无阻塞进程为止
(2)进程的换入
- 查看PCB集合中所有进程的状态,从中找出就绪状态但已换出的进程
- 选择其中已换出到磁盘上时间最久的进程作为换入进程
- 申请内存,成功则从外存调入内存,失败则先将内存中的某些进程换出,腾出足够的内存空间后再继续
5 分页存储管理方式
非连续分配允许一个程序分散地装入不相邻的内行分区。非连续分配方式的存储密度低于连续存储方式。
页内碎片:我们把主存空间划分为大小相等且固定的块,块相对较小,作为主存的基本单位。每个进程也以块为单位划分,进程在执行时,以块为单位逐个申请主存中的块空间。这样,进程只会在最后一个不完整的块申请一个主存块空间时,才会产生主存碎片,这种碎片相对于进程来说是很小的。
非连续分配管理方式根据分区的大小是否固定,分为分页存储管理方式和分段存储管理方式
5.1 分页存储管理的基本方法
(1)页面和物理块
进程中的块称为“页”;内存中的块称为“页框”;外存直接称为**“块”**。三者都以相同的单位进行划分。
进程在执行时需要申请主存空间,为每个页面分配主存中的可用页框,即进程中的页需要和主存中的页框一一对应
为了方便地址转换,页面大小应该为 2 的整数幂。页面的大小应该适当选择
- 过大:页内碎片增大
- 过小:页表增长,内存占用大
(2)地址结构
分页地址中的地址结构为:
其中 0 ~ 11 位为页内地址,表示每页的大小为 4KB;12 ~ 31 位为页号,表示地址空间最多允许有 1M 页
给定一个地址 A,若页面大小为 L,则页号 P 和页内地址 d 可以通过以下公式求出:
逻辑地址空间A,页面的大小L,页号P,页内地址d,INT是整除函数,MOD是取余函数
(3)页表
为了保证进程能够在内存中找到每个页面对应的物理块,需要为每个进程建立一张页面映像表,简称页表:
页表项的第二部分(块号 P)与地址的第二部分(页内偏移量 W)共同组成物理地址:
5.2 地址变换机构
地址变换机构的任务是将逻辑地址中的页号转换为内存中的物理块号,借助于页表来完成
(1)基本的地址变换机构
需要硬件支持,因为每条指令的地址都需要进行变换
在系统中只设置一组页表寄存器 PTR(Page-Table Register),存放页表在内存的起始地址 F 和页表长度 M。平时进程未执行时,页表的起始地址和长度存放在其 PCB 中,当调度程序调度到某进程时,将其装入 PTR 中。
当进程需要访问逻辑地址 A 中的数据时:
① 计算页号 P = A / L 和页内偏移量 W = A % L
② 比较页号 P 和页表长度 M ,若 P ≥ M ,则产生越界错误
③ 找出页号 P 对应的块号 b,类似于寻找数组元素的地址,( P , b ) 表项对应的地址计算公式为:
k 为页表项长度,即页地址占用的内存空间
④ 计算得到地址访问内存
采用这种方法,每条指令将访问 2 次内存:
- 访问页表,计算得到物理地址
- 访问物理地址得到值
(2)具有快表的地址变换机构
在地址变换机构中增设一个具有并行查找能力的高速缓冲存储器(Cache)——快表,也称相联存储器 / 联想寄存器(TLB),用来存放档期啊访问的若干表项。主存中的页表也相应地称为“慢表”。
地址变换过程:
① 计算 P 和 W 并检查 P 的长度
② 将 P 送入TLB 中,进行查找
- 若找到匹配的页号,直接取出对应的页框号,计算物理地址
- 若未找到,访问主存中的慢表,计算物理地址,同时将该页表项存入TLB中,方便后续查找,若TLB已满,则需要一定的替换策略选出其中的一项进行替换
快表通常只存放 16 ~ 512 个页表项,一般快表的命中率可达 90% 以上,这样分页带来的速度损失就可以降低到 10% 以下。
5.3 访问内存的有效时间
内存的有效访问时间(Effective Access Time):从进程发出指定逻辑地址的访问请求,经过地址变换,到在内存中找到对应的实际物理地址单元并取出数据,所需要花费的总时间。
(1)基于地址
假设访问一次内存的时间为 t,EAT=t + t =2t
(2)基于快表
假设 λ 为查找快表的时间,a 为命中率:
5.4 两级和多级页表
大多数计算机系统都支持非常大的逻辑地址空间(232 ~ 264)。假设对于一个具有 32 位的逻辑地址空间的分页系统,页面大小若为 4KB,则每个进程中页表的页表项可以达到 1M 之多,并且要求内存连续,这显然是不合实际的。因此,我们还需要考虑页表本身的大小。采用两个方法来解决:
① 对于页表需要的内存空间,可采用离散分配方式
② 只将当前需要的部分页表项调入内存,其余的页表项仍驻留在磁盘上
(1)离散分配页表—多级页表
我们可以将页表进行分页,使得每个页面的大小与内存物理块的大小相同,并为其编号,离散地将各个页面分别存放在不同的物理块中。因此,我们为页表再建立一张页表,称为外层页表,每个页表项中记录了页表页面的物理块号。
5.5 反置页表
(1)引入
在现代计算机系统中,通常允许一个进程的逻辑地址空间非常大,因此就需要有许多的页表项,而因此也会占用大量的内存空间。为了减少页表占用的内存空间,引入了反置页表。
反置页表为每一个物理块设置一个页表项,并将它们按物理块的编号排序,其中的内容则是页号和其所隶属进程的标识符
(2)地址的变换
① 根据进程的标识符和页号,检索反置页表
② 找到匹配的页表项时,其序号便是该页所在的物理块号(因为表项按物理块的编号排序),直接将其与页内地址进行计算得到物理地址
③若检索不到匹配的页表项,说明此页尚未调入内存
反置页表按照物理地址编号,而不是逻辑地址,因此可以大大减少内存的占用
6 分段存储管理方式
分段管理方式的提出则考虑了用户和程序员,以满足方便编程、信息保护和共享、动态增长及动态链接等多方面的需要
分页通过硬件机制实现,对用户完全透明,从计算机的角度考虑设计的。
6.1 分段存储管理方式的引入
通常的程序都可分为若干个段,如主程序段、子程序段 A、子程序段 B、… 、数据段以及栈段等,每个段大多是一个相对独立的逻辑单位。
分段存储管理方式更符合用户和程序员多方面的需要:
(1)方便编程
通常,用户把自己的作业按照逻辑关系划分为若干个段,每个段都从 0 开始编址,并有自己的名字和长度。程序员们都迫切地需要访问的逻辑地址是由段名(段号)和段内偏移量(段内地址)决定的。
优点:方便编程,程序直观,更具可读性
(2)信息共享
在实现对程序和数据的共享时,是以信息的逻辑单位为基础的。分页系统中的“页”只是存放信息的物理单位(块)。为共享的进程建立一个独立的段,极大简化了共享。
(3)信息保护
以信息的逻辑单位为基础,经常以一个过程、函数或文件为基本单位进行保护的。
例如,我们希望函数 A 仅允许进程执行,而不允许读,更不允许写,那么,我们只须在包含了函数 A 的这个段上标上只执行标志即可。在分页系统中,函数 A 可能要占用若干个页面,而且其中的第一个和最后一个页面还会装有其它程序段的数据,它们可能有着不同的保护属性,如可以允许进程读写,这样就很难对这些页面实施统一的保护。
因此分段管理更能有效和方便地实现对信息的保护功能
(4)动态增长
数据段在使用的过程中数据量会不断的增加,使数据段不断的动态增长,相应地它所需要的存储空间也会动态增加。
(5)动态链接
动态链接在作业运行之前,并不是把所有的目标程序段都链接起来。当程序要运行时,首先将主程序和它立即需要用到的目标程序装入内存,即启动运行。动态链接要求的是以目标程序(即段)作为链接的基本单位。
6.2 分段系统的基本原理
(1)分段
在分段存储管理方式中,作业的地址空间被划分为若干个段,每个段定义了一组逻辑信息
例如,有主程序段 MAIN、子程序段 X、数据段 D 及栈段 S 等,每个段都有自己的名字。为了实现简单起见,通常可用一个段号来代替段名,每个段都从 0 开始编址,并采用段连续的地址空间。
整个作业的地址空间由于被分成多个段,所以呈现出二维特性,亦即,每个段既包含了部分地址空间,又标识了逻辑关系。其逻地址由段号(段名)和段内地址所组成。
分段地址中的地址具有如下结构:
在地址结构中,允许作业最长有64K个段,每个段的最大长度64KB
(2)段表
为每个分段分配一个连续的分区,进程中的各个段,可以离散地装入内存中不同的分区中。
类似于分页系统,需为每个进程建立一张段映射表,简称“段表”。每个段在表中占有一个表项,其中记录了该段在内存中的起始地址(基址)和段的长度。
段表可以存放在一组寄存器中,以利于提高地址转换速度。但常见的是将段放在内存中。
段表是用于实现从逻辑段到物理内存区的映射的。
(3)地址变换机构
① 从逻辑地址 A 中取出段号 S,段内偏移量 W
② 比较 S 和 M 的长度,若S ≥ M ,则发生越界错误
③ 寻找段表中的段表项地址
F:段表的起始地址
K:段表项的长度
取出段长 C 后,与段内偏移量 W 比较,若 W ≥ C ,则产生越界错误
④ 取出该段的起始地址b,计算,得到地址后访问内存得到值
- 页式管理和段式管理区别:段式管理不能通过给出一个整数便确定对应的物理地址,因每段的长度是不固定的,无法通过整数除法得出段号,元法通过求余得出段内偏移。(S,W)一定要给出,地址是二维的。
(4)分页和分段的主要区别
① 页是信息的物理单位,段则是信息的逻辑单位
采用分页存储管理方式是为实现离散分配方式,以消减内存的外零头,提高内存的利用率,对用户不可见。
分段存储管理方式中的段则是信息的逻辑单位,它通常包含的是一组意义相对完整的信息。分段的目的主要在于能更好地满足用户的需要。
② 页的大小固定且由系统决定,而段的长度却不固定
分页存储管理方式在硬件结构上,就把用户程序的逻辑地址划分为页号和页内地址两部分,也就是说是直接由硬件实现的,因而在每个系统中只能有一种大小的页面。
段的长度却不固定,决定于用户所编写的程序,通常由编译程序在对源程序进行编译时,根据信息的性质来划分。
③ 分页的用户程序地址空间是一维的,分段的用户程序的地址空间是二维的
分页完全是系统的行为,用户程序的地址是属于单一的线性地址空间,程序员只需利用一个记忆符即可表示一个地址。
分段是用户的行为,用户程序的地址空间是二维的,程序员在标识一个地址时,既需给出段名,又需给出段内地址。
6.3 段页式存储管理方式
(1)在段页式系统中,作业的地址空间首先被分成若干逻辑段,每段都有自己的段号,然后将每段分成若干大小固定的页。对内存空间的管理仍然和分页存储管理一样,将其分成若干和页面大小相同的存储块,对内存的分配以存储块为单位。
段页式系统中,作业的逻辑地址分为三部分∶①段号 ② 页号 ③ 页内偏移量
作业地址空间和地址结构:
(2)地址变换过程
为了实现地址变换,系统为每个进程建立一张段表,每个分段有一张页表。段表表项中至少包括段号、页表长度和页表始址,页表表项中至少包括页号和块号。此外,系统中还应有一个段表寄存器,指出作业的段表始址和段表长度。
attention:在一个进程中,段表只有一个,页表可能有多个。
-
段表寄存器和页表寄存器的作用:① 在段表或页表中寻址 ② 判断是否越界
-
获得一条指令或数据,需要访问内存 3 次(计算机组成原理):
① 访问段表,获取页表的起始地址
② 访问页表,获取该页表所在的物理块号,与页内地址进行计算获得物理地址
③ 访问物理地址,获取数据
- 可以使用快表(TLB)加快查找速度:在地址变换机构中增设一个高速缓冲寄存器。每次访问它时,都须同时利用段号和页号去检索高速缓存,若找到匹配的表项,便可从中得到相应页的物理块号,用来与页内地址一起形成物理地址;若未找到匹配表项,则仍需第三次访问内存。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/16160.html