1.存储器的层次结构
2.程序的装入和链接
3.连续分配方式
4.基本分页存储管理方式
5.基本分段存储管理方式
存储器的层次结构
多级存储结构
对于通用计算机而言,存储层次至少应具有三级:最高层为CPU寄存器,中间为主存,最底层是辅存。在较高档的计算机中,还可以根据具体的功能分工细划为寄存器、高速缓存、主存储器、磁盘缓存、固定磁盘、可移动存储介质等6层。如图4-1所示,在存储层次中越往上,存储介质的访问速度越快,价格也越高,相对存储容量也越小。其中,寄存器、高速缓存、主存储器和磁盘缓存均属于操作系统存储管理的管辖范畴,掉电后它们存储的信息不再存在。固定磁盘和可移动存储介质属于设备管理的管辖范畴,它们存储的信息将被长期保存。
主存储器与寄存器
主存储器
主存储器(简称内存或主存)是计算机系统中一个主要部件,用于保存进程运行时的程序和数据,也称可执行存储器,其容量对于当前的微机系统和大中型机,可能一般为数十MB到数GB,而且容量还在不断增加,而嵌入式计算机系统一般仅有几十KB到几MB。CPU的控制部件只能从主存储器中取得指令和数据,数据能够从主存储器读取并将它们装入到寄存器中,或者从寄存器存入到主存储器。CPU与外围设备交换的信息一般也依托于主存储器地址空间。由于主存储器的访问速度远低于CPU执行指令的速度,为缓和这一矛盾,在计算机系统中引入了寄存器和高速缓存。
寄存器
寄存器访问速度最快,完全能与CPU协调工作,但价格却十分昂贵,因此容量不可能做得很大。寄存器的长度一般以字(word)为单位。寄存器的数目,对于当前的微机系统和大中型机,可能有几十个甚至上百个;而嵌入式计算机系统一般仅有几个到几十个。寄存器用于加速存储器的访问速度,如用寄存器存放操作数,或用作地址寄存器加快地址转换速度等。
高速缓存和磁盘缓存
高速缓存
高速缓存是现代计算机结构中的一个重要部件,其容量大于或远大于寄存器,而比内存约小两到三个数量级左右,从几十KB到几MB,访问速度快于主存储器。
根据程序执行的局部性原理(即程序在执行时将呈现出局部性规律,在一较短的时间内,程序的执行仅局限于某个部分),将主存中一些经常访问的信息存放在高速缓存中,减少访问主存储器的次数,可大幅度提高程序执行速度。
磁盘缓存
由于目前磁盘的I/O速度远低于对主存的访问速度,因此将频繁使用的一部分磁盘数据和信息,暂时存放在磁盘缓存中,可减少访问磁盘的次数。磁盘缓存本身并不是一种实际存在的存储介质,它依托于固定磁盘,提供对主存储器存储空间的扩充,即利用主存中的存储空间,来暂存从磁盘中读出(或写入)的信息。主存也可以看做是辅存的高速缓存,因为,辅存中的数据必须复制到主存方能使用;反之,数据也必须先存在主存中,才能输出到辅存。
一个文件的数据可能出现在存储器层次的不同级别中,例如,一个文件数据通常被存储在辅存中(如硬盘),当其需要运行或被访问时,就必须调入主存,也可以暂时存放在主存的磁盘高速缓存中。大容量的辅存常常使用磁盘,磁盘数据经常备份到磁带或可移动磁盘组上,以防止硬盘故障时丢失数据。有些系统自动地把老文件数据从辅存转储到海量存储器中,如磁带上,这样做还能降低存储价格。
内存管理功能总结
- 内存分配与回收:(空间记录表格设计、分配/回收算法)
- 地址转换:逻辑地址--->物理地址(装入程序,表、地址转换机构、处理算法)
- 内存保护:防止越界、非法访问。(界地址/限长寄存器,表格、处理算法)
- 内存共享:多个进程--->一个程序。(可重入代码,共享计数器,访问权限,处理算法)
- 内存扩充:逻辑扩充,小内存运行大程序。(覆盖、交换、虚拟存储器)
内存的分配与回收
内存分配按分配时机的不同,可分为三种方式:
(1)直接分配
这种方式是指程序员采用物理内存地址编写程序。使用这种方式,必须事先划定内存的使用空间,因此,这种方式下的内存利用率不高,用户使用较困难。
(2)静态分配
指内存分配是在作业运行之前各目标模块连接后,把整个作业一次性全部装入内存,并在作业的整个运行过程中,不允许作业再申请其他内存,或在内存中移动位置。也就是说,内存分配是在作业运行前一次性完成的。
(3)动态分配
作业要求的基本内存空间是在目标模块装入内存时分配的,但在作业运行过程中,允许作业申请附加的内存空间,或是在内存中移动,即分配工作可以在作业运行前及运行过程中逐步完成。
地址转换
把用户程序装入内存时对有关指令的地址部分的修改定义为从程序地址到内存地址的地址转换,或称为地址重定位。
物理地址:内存地址,它是用于唯一标识一个内存单元的编号。所有的物理地址构成了物理空间。
逻辑地址:程序地址/相对地址/虚地址。它是指在源程序经过汇编或编译后形成的目标代码中,用于反映目标代码中指令或数据的相对位置关系的地址。逻辑地址都是以“0”为基址顺序进行编址的,这样生成的目标程序占据一定的地址空间,称为程序的逻辑地址空间,简称逻辑空间。
符号地址(符号名):表示的程序空间称为名空间。
地址重定位的原因是因为程序在装入内存后,其逻辑地址和内存地址不一致。
内存的共享与保护
内存共享:
多个进程共享内存中的同一段信息。
优点:节省内存空间,减少I/O量,提高性能。
实现:1,代码必须是可重入的。2, 必须设置共享的数据结构(如共享计数器等),并管理这个数据结构。
内存保护:
防止进程的数据被非法访问;防止越界
防止非法访问:设权限位;存储键
防止越界:1,上、下界存储保护:系统可为每个作业设置一对上、下界寄存器,分别用来存放当前运行作业在内存空间的上、下边界地址,用它们来限制用户程序的活动范围。2,基址-限长存储保护:上、下界保护的一个变种是采用基址—限长存储保护。
内存扩充
对内存进行逻辑上的扩充,现在普遍采用覆盖、交换和虚拟存储器技术。
虚拟存储器:程序不完整存放的自动透明实现技术。具有请求调入功能和置换功能,能仅把作业的一部分装入内存便可运行作业的存储器系统。
虚拟存储器的理论基础是程序的局部性原理。
- 时间局部性:某段刚被访问的信息,可能很快会被再次访问。
- 空间局部性:某段信息刚被访问,其相邻单元信息可能很快会被访问。
虚拟存储器的基本思想是把有限的内存空间与大容量的外存统一管理,构成一个远大于实际内存的、虚拟的存储器。此时,外存是作为内存的直接延伸,用户并不会感觉到内、外存的区别,即把两级存储器当作一级存储器来看待。一个作业运行时,其全部信息装入虚存,实际上可能只有当前运行的必需一部分信息存入内存,其他则存于外存,当所访问的信息不在内存时,系统自动将其从外存调入内存。
虚存的容量(虚存技术下用户程序所看到的逻辑地址空间):指令的地址部分所表示的最大空间,如用n个二进制位表示地址,则虚存大小为2^n-1
存储管理的几个概念
存储碎片:一段连续的用不上的存储空间
- 内部碎片:系统分给了进程,但进程不需要
- 外部碎片:空间太小,任何进程都不够用,系统分不出去
移动/内存合并:解决内存碎片问题,通过内存中进程空间的移动(重定位),将几个碎片合并在一起,变成有用的空间。
连续:进程的地址空间逻辑上连续,物理上(在内存)也连续。
完整:进程的地址空间全部存放在内存(不需实现虚存技术)。
移动与虚存技术就是拿CPU时间换存储空间的技术。
存储管理方案
连续分配方式:
非连续分配方式:
①分区缺点:由于进程空间逻辑上连续,物理上也连续,因此带来内存利用率低、共享难、有碎片、无法实现虚存。
②不连续技术可以避免移动、实现共享、实现虚存、避免外部碎片,关键是地址转换如何解决?多对寄存器可以,但硬件开销太大。
③页式、段式、段页式可以解决上述问题。
页式实现
1.OS管理,整个物理内存分系统区和用户区。
2.内存分为等长页面(frame),称为块或页帧。
3.进程的地址空间划分成等长页(page),页与页面通常等长。
4.程序在内存存放时,页内连续、页间不一定连续(即相邻页不一定放在相邻页面中)。
5.程序不一定完整进入内存(实存/虚存)。
页面与页表
页面
页面和物理块
分页存储管理是将一个进程的逻辑地址空间分成若干个大小相等的片,称为页面或页,并为各页加以编号,从0开始,如第0页、第1页等。相应地,也把内存空间分成与页面相同大小的若干个存储块,称为(物理)块或页框(frame),也同样为它们加以编号,如0#块、1#块等等。在为进程分配内存时,以块为单位将进程中的若干个页分别装入到多个可以不相邻接的物理块中。由于进程的最后一页经常装不满一块而形成了不可利用的碎片,称之为“页内碎片”。
页面大小
在分页系统中的页面其大小应适中。页面若太小,一方面虽然可使内存碎片减小,从而减少了内存碎片的总空间,有利于提高内存利用率,但另一方面也会使每个进程占用较多的页面,从而导致进程的页表过长,占用大量内存;此外,还会降低页面换进换出的效率。然而,如果选择的页面较大,虽然可以减少页表的长度,提高页面换进换出的速度,但却又会使页内碎片增大。因此,页面的大小应选择适中,且页面大小应是2的整数次幂,通常为512 B~8 KB。
地址结构
分页地址中的地址结构如下:
它含有两部分:前一部分为页号P,后一部分为位移量W(或称为页内地址)。图中的地址长度为32位,其中0~11位为页内地址,即每页的大小为4 KB;12~31位为页号,地址空间最多允许有1 M页。
对于某特定机器,其地址结构是一定的。若给定一个逻辑地址空间中的地址为A,页面的大小为L,则页号P和页内地址d可按下式求得:
其中,INT是整除函数,MOD是取余函数。例如,其系统的页面大小为1 KB,设A = 2170 B,则由上式可以求得P = 2,d = 122。
页表
在分页系统中,允许将进程的各个页离散地存储在内存不同的物理块中,但系统应能保证进程的正确运行,即能在内存中找到每个页面所对应的物理块。为此,系统又为每个进程建立了一张页面映像表,简称页表。在进程地址空间内的所有页(0~n),依次在页表中有一页表项,其中记录了相应页在内存中对应的物理块号,见图4-12的中间部分。在配置了页表后,进程执行时,通过查找该表,即可找到每页在内存中的物理块号。可见,页表的作用是实现从页号到物理块号的地址映射。
地址变换机构
基本的地址变换机构
页表的功能可以由一组专门的寄存器来实现。一个页表项用一个寄存器。由于寄存器具有较高的访问速度,因而有利于提高地址变换的速度;但由于寄存器成本较高,且大多数现代计算机的页表又可能很大,使页表项的总数可达几千甚至几十万个,显然这些页表项不可能都用寄存器来实现,因此,页表大多驻留在内存中。在系统中只设置一个页表寄存器PTR(Page-Table Register),在其中存放页表在内存的始址和页表的长度。平时,进程未执行时,页表的始址和页表长度存放在本进程的PCB中。当调度程序调度到某进程时,才将这两个数据装入页表寄存器中。因此,在单处理机环境下,虽然系统中可以运行多个进程,但只需一个页表寄存器。
当进程要访问某个逻辑地址中的数据时,分页地址变换机构会自动地将有效地址(相对地址)分为页号和页内地址两部分,再以页号为索引去检索页表。查找操作由硬件执行。在执行检索之前,先将页号与页表长度进行比较,如果页号大于或等于页表长度,则表示本次所访问的地址已超越进程的地址空间。于是,这一错误将被系统发现并产生一地址越界中断。若未出现越界错误,则将页表始址与页号和页表项长度的乘积相加,便得到该表项在页表中的位置,于是可从中得到该页的物理块号,将之装入物理地址寄存器中。与此同时,再将有效地址寄存器中的页内地址送入物理地址寄存器的块内地址字段中。这样便完成了从逻辑地址到物理地址的变换。图4-13示出了分页系统的地址变换机构。
具有快表的地址变换机构
由于页表是存放在内存中的,这使CPU在每存取一个数据时,都要
两次访问内存。第一次是访问内存中的页表,从中找到指定页的物理块号,再将块号与页内偏移量W拼接,以形成物理地址。第二次访问内存时,才是从第一次所得地址中获得所需数据(或向此地址中写入数据)。因此,采用这种方式将使计算机的处理速度降低近1/2。可见,以此高昂代价来换取存储器空间利用率的提高,是得不偿失的。
为了提高地址变换速度,可在地址变换机构中增设一个具有并行查寻能力的特殊高速缓冲寄存器,又称为“联想寄存器”(Associative Memory),或称为“快表”,在IBM系统中又取名为TLB(Translation Lookaside Buffer),用以存放当前访问的那些页表项。此时的地址变换过程是:在CPU给出有效地址后,由地址变换机构自动地将页号P送入高速缓冲寄存器,并将此页号与高速缓存中的所有页号进行比较,若其中有与此相匹配的页号,便表示所要访问的页表项在快表中。于是,可直接从快表中读出该页所对应的物理块号,并送到物理地址寄存器中。如在块表中未找到对应的页表项,则还须再访问内存中的页表,找到后,把从页表项中读出的物理块号送地址寄存器;同时,再将此页表项存入快表的一个寄存器单元中,亦即,重新修改快表。但如果联想寄存器已满,则OS必须找到一个老的且已被认为不再需要的页表项,将它换出。图 4-14示出了具有快表的地址变换机构。
两级和多级页表
现代的大多数计算机系统,都支持非常大的逻辑地址空间(232~264)。在这样的环境下,页表就变得非常大,要占用相当大的内存空间。例如,对于一个具有32位逻辑地址空间的分页系统,规定页面大小为4 KB即212 B,则在每个进程页表中的页表项可达1兆个之多。又因为每个页表项占用一个字节,故每个进程仅仅其页表就要占用1 MB的内存空间,而且还要求是连续的。显然这是不现实的,我们可以采用下述两个方法来解决这一问题:
(1) 采用离散分配方式来解决难以找到一块连续的大内存空间的问题;
(2) 只将当前需要的部分页表项调入内存,其余的页表项仍驻留在磁盘上,需要时再调入。
页式管理的分配与回收(位示图)
- 计算一个作业所需要的总块数N;
- 查位示图,看看是否还有N个空闲块;
- 如果有足够的空闲块,则页表长度设为N,申请页表区,把页表始址填入PCB;
- 依次分配N个空闲块,将块号和页号填入页表;
- 修改位示图。
页式特点
(1)优点:
分配与回收简单
消除“碎片”问题
可实现虚存、共享
(2)缺点:
页面划分不考虑程序的逻辑结构
共享受限
不能动态链接
二次访内,速度慢
基本分段存储管理方式
分段存储管理方式的引入
1) 方便编程
通常,用户把自己的作业按照逻辑关系划分为若干个段,每个段都是从0开始编址,并有自己的名字和长度。因此,希望要访问的逻辑地址是由段名(段号)和段内偏移量(段内地址)决定的。例如,下述的两条指令便是使用段名和段内地址:
LOAD 1,[A] |〈D〉;
STORE 1,[B] |〈C〉;
其中,前一条指令的含义是将分段A中D单元内的值读入寄存器1;后一条指令的含义是将寄存器1的内容存入B分段的C单元中。
2) 信息共享
在实现对程序和数据的共享时,是以信息的逻辑单位为基础的。比如,共享某个例程和函数。分页系统中的“页”只是存放信息的物理单位(块),并无完整的意义,不便于实现共享;然而段却是信息的逻辑单位。由此可知,为了实现段的共享,希望存储管理能与用户程序分段的组织方式相适应。
3) 信息保护
信息保护同样是对信息的逻辑单位进行保护,因此,分段管理方式能更有效和方便地实现信息保护功能。
4) 动态增长
在实际应用中,往往有些段,特别是数据段,在使用过程中会不断地增长,而事先又无法确切地知道数据段会增长到多大。前述的其它几种存储管理方式,都难以应付这种动态增长的情况,而分段存储管理方式却能较好地解决这一问题。
5) 动态链接
动态链接是指在作业运行之前,并不把几个目标程序段链接起来。要运行时,先将主程序所对应的目标程序装入内存并启动运行,当运行过程中又需要调用某段时,才将该段(目标程序)调入内存并进行链接。可见,动态链接也要求以段作为管理的单位。
分段系统的基本原理
- 将用户程序空间按逻辑划分为几段(segment),每个段内连续编址,每个程序段都有一个段名,且有一个段号。段号从0开始,每一段段内也从0开始编址,段内地址是连续的段间是不一定连续编址的
- 以段为单位分配内存,段内连续完整,但各段之间可以不连续存放
- 段式逻辑地址二维:<段号><段内位移>
- 每个进程一张段表,实现地址转换、信息保护、共享、扩充、动态连接等
1.分段
在分段存储管理方式中,作业的地址空间被划分为若干个段,每个段定义了一组逻辑信息。例如,有主程序段MAIN、子程序段X、数据段D及栈段S等,如图4-17所示。每个段都有自己的名字。为了实现简单起见,通常可用一个段号来代替段名,每个段都从0开始编址,并采用一段连续的地址空间。段的长度由相应的逻辑信息组的长度决定,因而各段长度不等。整个作业的地址空间由于是分成多个段,因而是二维的,亦即,其逻辑地址由段号(段名)和段内地址所组成。
分段地址中的地址具有如下结构:
在该地址结构中,允许一个作业最长有 64 K个段,每个段的最大长度为64 KB。
分段方式已得到许多编译程序的支持,编译程序能自动地根据源程序的情况而产生若干个段。例如,Pascal编译程序可以为全局变量、用于存储相应参数及返回地址的过程调用栈、每个过程或函数的代码部分、每个过程或函数的局部变量等等,分别建立各自的段。类似地,Fortran编译程序可以为公共块(Common block)建立单独的段,也可以为数组分配一个单独的段。装入程序将装入所有这些段,并为每个段赋予一个段号。
2.段表
在前面所介绍的动态分区分配方式中,系统为整个进程分配一个连续的内存空间。而在分段式存储管理系统中,则是为每个分段分配一个连续的分区,而进程中的各个段可以离散地移入内存中不同的分区中。为使程序能正常运行,亦即,能从物理内存中找出每个逻辑段所对应的位置,应像分页系统那样,在系统中为每个进程建立一张段映射表,简称“段表”。每个段在表中占有一个表项,其中记录了该段在内存中的起始地址(又称为“基址”)和段的长度,如图4-17 所示。段表可以存放在一组寄存器中,这样有利于提高地址转换速度,但更常见的是将段表放在内存中。
3.地址变换机构
为了实现从进程的逻辑地址到物理地址的变换功能,在系统中设置了段表寄存器,用于存放段表始址和段表长度TL。在进行地址变换时,系统将逻辑地址中的段号与段表长度TL进行比较。若S>TL,表示段号太大,是访问越界,于是产生越界中断信号;若未越界,则根据段表的始址和该段的段号,计算出该段对应段表项的位置,从中读出该段在内存的起始地址,然后,再检查段内地址d是否超过该段的段长SL。若超过,即d>SL,同样发出越界中断信号;若未越界,则将该段的基址d与段内地址相加,即可得到要访问的内存物理地址。图4-18示出了分段系统的地址变换过程。
像分页系统一样,当段表放在内存中时,每要访问一个数据,都须访问两次内存,从而极大地降低了计算机的速率。解决的方法也和分页系统类似,再增设一个联想存储器,用于保存最近常用的段表项。由于一般情况是段比页大,因而段表项的数目比页表项的数目少,其所需的联想存储器也相对较小,便可以显著地减少存取数据的时间,比起没有地址变换的常规存储器的存取速度来仅慢约10%~15%。
4.分页和分段的主要区别
由上所述不难看出,分页和分段系统有许多相似之处。比如,两者都采用离散分配方式,且都要通过地址映射机构来实现地址变换。但在概念上两者完全不同,主要表现在下述三个方面。
(1) 页是信息的物理单位,分页是为实现离散分配方式,以消减内存的外零头,提高内存的利用率。或者说,分页仅仅是由于系统管理的需要而不是用户的需要。段则是信息的逻辑单位,它含有一组其意义相对完整的信息。分段的目的是为了能更好地满足用户的需要。
(2) 页的大小固定且由系统决定,由系统把逻辑地址划分为页号和页内地址两部分,是由机器硬件实现的,因而在系统中只能有一种大小的页面;而段的长度却不固定,决定于用户所编写的程序,通常由编译程序在对源程序进行编译时,根据信息的性质来划分。
(3) 分页的作业地址空间是一维的,即单一的线性地址空间,程序员只需利用一个记忆符,即可表示一个地址;而分段的作业地址空间则是二维的,程序员在标识一个地址时,既需给出段名,又需给出段内地址。
信息共享
分段系统的一个突出优点,是易于实现段的共享,即允许若干个进程共享一个或多个分段,且对段的保护也十分简单易行。在分页系统中,虽然也能实现程序和数据的共享,但远不如分段系统来得方便。我们通过一个例子来说明这个问题。例如,有一个多用户系统,可同时接纳40个用户,他们都执行一个文本编辑程序(Text Editor)。如果文本编辑程序有160 KB的代码和另外40 KB的数据区,则总共需有 8 MB的内存空间来支持40个用户。如果160 KB的代码是可重入的(Reentrant),则无论是在分页系统还是在分段系统中,该代码都能被共享,在内存中只需保留一份文本编辑程序的副本,此时所需的内存空间仅为1760 KB(40×40+160),而不是8000 KB。
假定每个页面的大小为4 KB,那么,160 KB的代码将占用40个页面,数据区占10个页面。为实现代码的共享,应在每个进程的页表中都建立40个页表项,它们的物理块号都是21#~60#。在每个进程的页表中,还须为自己的数据区建立页表项,它们的物理块号分别是61#~70#、71#~80#、81#~90#,…,等等。图4-19是分页系统中共享editor的示意图。
在分段系统中,实现共享则容易得多,只需在每个进程的段表中为文本编辑程序设置一个段表项。图4-20是分段系统中共享editor的示意图。
段式特点
1.优点:
符合用户观点和程序逻辑
易于保护
易于共享
易于动态链接
易于动态扩充
可以实现虚存
2.缺点:
分配回收同可变式分区,实现复杂
虚存技术较好的解决装不下问题,没有页式好
存在二次访内指令执行速度慢问题,需联想存储器支持
有外部碎片,需移动开销
段页式存储管理方式
段页式引入:
- 段式优于页式:便于共享和保护、动态伸缩、动态链接
- 页式优于段式:消除“碎片”问题、分配与回收简单
- 段页式:结合二者优点
分配与回收:同页式
共享与保护、动态伸缩、动态链接:同段式
段页式存储管理实现
1.进程分为若干段(一个进程有一张段表),每段由若干页组成(每段有一张自己的页表)。
2.内存分页面、存储管理的分配单位是页
3.逻辑地址:二维<段号,段内地址>
<段号,页号,页内偏移>
4.地址变换:先查段表,再查该段的页表。请求式系统中存在缺段中断和缺页中断。
基本原理
段页式系统的基本原理,是分段和分页原理的结合,即先将用户程序分成若干个段,再把每个段分成若干个页,并为每一个段赋予一个段名。图4-21示出了一个作业地址空间的结构。该作业有三个段,页面大小为4 KB。在段页式系统中,其地址结构由段号、段内页号及页内地址三部分所组成,如图4-22所示。
地址变换过程
在段页式系统中,为了便于实现地址变换,须配置一个段表寄存器,其中存放段表始址和段表长TL。进行地址变换时,首先利用段号S,将它与段表长TL进行比较。若S
在段页式系统中,为了获得一条指令或数据,须三次访问内存。第一次访问是访问内存中的段表,从中取得页表始址;第二次访问是访问内存中的页表,从中取出该页所在的物理块号,并将该块号与页内地址一起形成指令或数据的物理地址;第三次访问才是真正从第二次访问所得的地址中,取出指令或数据。
显然,这使访问内存的次数增加了近两倍。为了提高执行速度,在地址变换机构中增设一个高速缓冲寄存器。每次访问它时,都须同时利用段号和页号去检索高速缓存,若找到匹配的表项,便可从中得到相应页的物理块号,用来与页内地址一起形成物理地址;若未找到匹配表项,则仍须再三次访问内存。
段页式特点
分配与回收:同页式
共享与保护、动态伸缩、动态链接:同段式
三次访内,必须联想存储器支持
碎片:n倍于页式