非连续分配允许一个程序分散地装入到不相邻的内存分区中,根据分区的大小是否固定分为分页存储管理方式和分段存储管理方式。在分页存储管理方式中,如果不具备页面对换功能,则称为基本分页存储管理方式,或纯分页管理方式。
基本分页存储管理方式
固定分区会产生内部碎片,动态分区会产生外部碎片,这两种技术对内存的利用率都比较低。为尽量避免碎片的产生,引入了分页的思想:把主存空间划分为大小相等且固定的块,块相对较小,作为主存的基本单位。每个进程也以块为单位进行划分,进程在执行时,以块为单位逐个申请主存中的块空间。
分页方法与固定分区技术不同点在于:块的大小相对于分区小很多,而且进程也按照块进行划分,进程运行时,按照块申请主存可用空间并执行。与分区留在较大的内部碎片不同,分页方式只会在最后一个主存块上留下页内碎片。
1 分页存储的几个基本概念
1.1 页面和页面大小
进程中的块称为页(Page),内存中的块称为页框或页帧(Page Frame)。外存也以同样的单位进行划分,直接称为块(Block)。进程在执行时需要申请主存空间,就是要为每个页面分配主存中的可用页框,页与页框的一一对应。
为方便地址转换,页面大小应是2的整数幂,通常是512B~8KB。同时页面大小应该适中,需要进行空间效率和时间效率的权衡。如果页面太小,会使进程的页面数过多,这样页表就过长,占用大量内存,而且也会增加硬件地址转换的开销,降低页面换入/换出的效率;页面过大又会使页内碎片增大,降低内存的利用率。
1.2 地址结构
分页存储管理的逻辑地址结构如图所示:
地址结构包含两部分:前一部分为页号P,后一部分为页内偏移量W。地址长度为32 位,其中0 11位为页内地址,即每页大小为4KB;1231位为页号,地址空间最多允许有2^20(1M)页。
1.3 页表
为了便于在内存中找到进程的每个页面所对应的物理块,系统为每个进程建立一张页表,记录页面在内存中对应的物理块号,页表一般存放在内存中。
进程通过查表得到每页在内存中的物理块号。由页表实现了从页号到物理块号的地址映射。如下图所示:
2 基本地址变换机构
地址变换机构的任务是将逻辑地址转换为内存中物理地址,地址变换是借助于页表实现的。转换过程中,业内偏移是固定的,需要完成由页号到块号的变换。
在系统中通常设置一个页表寄存器(PTR),存放页表在内存的始址F和页表长度M。进程未执行时,页表的始址和长度存放在进程控制块中,当进程执行时,才将页表始址和长度存入页表寄存器。设页面大小为L,逻辑地址A到物理地址E的变换过程如下:
- 计算页号P(P=A/L)和页内偏移量W (W=A%L)。
- 比较页号P和页表长度M,若P >= M,则产生越界中断,否则继续执行。
- 页表中页号P对应的页表项地址 = 页表起始地址F + 页号P * 页表项长度,取出该页表项内容b,即为物理块号。
- 计算E=b*L+W,用得到的物理地址E去访问内存。
以上整个地址变换过程均是由硬件自动完成的。
3 具备快表的地址变换机构
若页表全部放在内存中,则存取一个数据或一条指令至少要访问两次内存:一次是访问页表,确定所存取的数据或指令的物理地址,第二次才根据该地址存取数据或指令。这种方法比通常执行指令的速度慢了一半。
为加速地址变换的过程,在地址变换机构中增设了一个具有并行查找能力的高速缓冲存储器——快表,又称联想寄存器(TLB),用来存放当前访问的若干页表项。与此对应,主存中的页表也常称为慢表,配有快表的地址变换机构如图所示:
在具有快表的分页机制中,地址的变换过程:
- CPU给出逻辑地址后,由硬件进行地址转换并将页号送入高速缓存寄存器,并将此页号与快表中的所有页号进行比较。
- 如果在快表中找到匹配的页号,则直接从中取出该页对应的页框号,与页内偏移量拼接形成物理地址。这样,存取数据仅一次访存便可实现。
- 如果没有找到,则需要访问主存中的页表,在读出页表项后,应同时将其存入快表,以便后面可能的再次访问。但若快表已满,则必须按照一定的算法对旧的页表项进行替换。
有些处理机设计为快表和慢表同时查找,如果在快表中查找成功则终止慢表的查找。一般快表的命中率可以达到90%以上,这样,分页带来的速度损失就降低到10%以下。
4 两级和多级页表
现代大多数计算机系统都支持非常大的逻辑地址空间(232~264),在这样的环境下,页表就变得非常大,要占很大的内存空间。32 位逻辑地址空间、页面大小4KB、页表项大小4B为例,若要实现进程对全部逻辑地址空间的映射,则每个进程需要2^20个页表项。也就是说,每个进程仅页表这一项就需要4MB主存空间,这显然是不切实际的。
此问题解决分两方面:一方面,只将当前需要的部分表项调入内存,其余的页表仍然驻留在磁盘上,需要时再调入。另一方面,需要对页表映射的思想进一步延伸,就可以得到二级分页。
二级页表将页表的10页空间也进行地址映射,建立上一级页表,用于存储页表的映射关系。上一级页表只需要1页就足够(可以存储2^10=1024个页表项)。在进程执行时,只需要将这1页的上一级页表调入内存即可,进程的页表和进程本身的页面,可以在后面的执行中再调入内存。
对二级页表再进行拓展,得到多级页表。64位计算机通常将可寻址存储空间减少为45位长度,这样可以使用三级页表结构来实现分页存储管理。
基本分段存储管理方式
分页管理方式是从计算机的角度考虑设计的,以提高内存的利用率,提升计算机的性能, 且分页通过硬件机制实现,对用户完全透明;而分段管理方式的提出则是考虑了用户和程序员,以满足方便编程、信息保护和共享、动态增长及动态链接等多方面的需要。
1 分段
段式管理方式按照用户进程中的自然段划分逻辑空间。例如,用户进程由主程序、两个子程序、栈和一段数据组成,于是可以把这个用户进程划分为5个段,每段从0 开始编址,并分配一段连续的地址空间(段内要求连续,段间不要求连续,因此整个作业的地址空间是二维的)。其逻辑地址由段号S与段内偏移量W两部分组成。
下图中,段号是16位,段内偏移量是为16位,则一个作业最多可有216=65536个段,最大段长为64KB。
在页式系统中,逻辑地址的页号和页内偏移量对用户是透明的,但在段式系统中,段号和段内偏移量必须由用户显示提供,在髙级程序设计语言中,这个工作由编译程序完成。
2 段表
每个进程都有一张逻辑空间与内存空间映射的段表,其中每一个段表项对应进程的一个段,段表项记录该段在内存中的起始地址和段的长度。段表的内容如图所示:
段表用于实现从逻辑段到物理内存区的映射。在配置了段表后,执行中的进程可通过查找段表,找到每个段所对应的内存区。
3 地址变换机构
为了实现进程从逻辑地址到物理地址的变换功能,在系统中设置了段表寄存器,用于存放段表始址F和段表长度M。其从逻辑地址A到物理地址E之间的地址变换过程如下:
- 从逻辑地址A中取出前几位为段号S,后几位为段内偏移量W。
- 比较段号S和段表长度M,若S多M,则产生越界中断,否则继续执行。
- 段表中段号S对应的段表项地址 = 段表起始地址F + 段号S * 段表项长度,取出该段表项的前几位得到段长C。若段内偏移量>=C,则产生越界中断,否则继续执行。
- 取出段表项中该段的起始地址b,计算 E = b + W,用得到的物理地址E去访问内存。
分段系统的地址变换过程如下图所示:
4 段的共享与保护
在分段系统中,段的共享是通过两个作业的段表中相应表项指向被共享的段的同一个物理副本来实现的。当一个作业正从共享段中读取数据时,必须防止另一个作业修改此共享段中的数据。
不能修改的代码称为纯代码或可重入代码(它不属于临界资源)。这样的代码和不能修改的数据是可以共享的,而可修改的代码和数据则不能共享。(需要修改数据时,每个访问进程必须配置局部数据区,并在执行中可能改变的部分拷贝到该区域)
与分页管理类似,分段管理的保护方法主要有两种:一种是存取控制保护,另一种是地址越界保护。地址越界保护是利用段表寄存器中的段表长度与逻辑地址中的段号比较,若段号大于段表长度则产生越界中断;再利用段表项中的段长和逻辑地址中的段内位移进行比较,若段内位移大于段长,也会产生越界中断。
段页式管理方式
页式存储管理能有效地提高内存利用率,而分段存储管理能反映程序的逻辑结构并有利于段的共享。如果将这两种存储管理方法结合起来,就形成了段页式存储管理方式。
在段页式系统中,作业的地址空间首先被分成若干个逻辑段,每段都有自己的段号,然后再将每一段分成若干个大小固定的页。对内存空间的管理仍然和分页存储管理一样,将其分成若干个和页面大小相同的存储块,对内存的分配以存储块为单位,如图所示:
在段页式系统中,作业的逻辑地址分为三部分:段号、页号和页内偏移量:
注意:在一个进程中,段表只有一个,而页表可能有多个。
在进行地址变换时,首先通过段表查到页表起始地址,然后通过页表找到页帧号,最后形成物理地址。如图所示,进行一次访问实际需要三次访问主存,这里同样可以使用快表以加快查找速度,其关键字由段号、页号组成,值是对应的页帧号和保护码。