内存的基础知识
- 绝对装入(静态装入)由编译器(此时还没有OS)把物理地址计算好。
只适用于单道程序环境,可以由编译器来决定物理地址,也可以由程序员在汇编代码中直接给出。
- 可重定位装入(静态重定位)是在装入阶段把逻辑地址转换为物理地址。
适用于多道程序环境下。适用于固定分区方式,作业装入后不能移动。
- 动态运行时装入(动态重定位)是在执行阶段再决定将哪部分模块的逻辑地址转换为物理地址装入,并且装入后可能有换出,所以同一个模块在内存内的物理地址是可能移动的。
适用于多道程序环境下。
可以将程序分配到不连续的存储区(因为此时已经出现了分页/分段技术)
重定位寄存器(基地址寄存器)含最小的物理地址,界地址寄存器含最大的逻辑地址,内存管理机构动态地将逻辑地址与界地址寄存器进行比较,没有越界的话,和重定位寄存器相加后再映射位物理地址。
装入时将逻辑地址转换为物理地址的过程,称为地址重定位。
链接程序后构成的统一的从0号单元开始编址的线性地址空间称为逻辑地址空间(或虚拟地址空间)。对于32位机器,逻辑地址空间的范围为0~232 -1 。即逻辑地址空间大小取决于地址总线的宽度(可以比物理地址空间还大,例如64位机器理论上虚拟地址空间可以很大很大)。
进程在运行时看到的和使用的都是逻辑地址,不同进程可以有相同的逻辑地址,因为这些相同的逻辑地址可以映射到主存的不同位置。
关于内存保护:
内存保护需要由硬件(界地址寄存器等)和操作系统一起实现。
关于内存共享:
只有可重入代码(纯代码)可以共享(也就是说只读的区域才能共享)。 但在执行中可以将共享区域复制到进程私有的数据区中进行修改,共享区域的代码不受影响。
实现共享内存的方式:
- 分段机制
- 内存映射文件
- 交换需要备份存储(磁盘)。所以空间要大,并提供对这些内存映像的直接访问。(内存映射文件?)
- 为了有效使用CPU,进程的执行时间需要大于交换时间。
补充 进程的内存映像:
- 代码段:只读的,可被共享。
- 数据段:运行时加工处理的对象,包括全局变量与局部变量。
- PCB:存放在系统区。
- 堆:用来存放动态分配的变量。例如通过malloc动态地向高地址分配空间。
- 栈:用来实现函数调用。从用户空间的最大地址向低地址增长。
代码段和数据段在装入时就指定了大小。堆和栈可以动态的收缩。
连续分配技术
动态分区分配算法
非连续分配技术
基本分页存储管理
逻辑地址空间 肯定要比 物理地址空间 大 :由于虚拟存储技术(请求分页,换入换出技术)
进程的逻辑地址空间 | 内存的物理地址空间 |
---|---|
页、页面、Page | 页框、页帧、物理页(面)、物理块、内存块、Page Frame |
页号、页面号 | 页框号、页帧号、物理页号 |
页表实质上就是页号与页框号的映射关系。
页面太小会使页面数过多,页表过长占用内存,而且会增加地址转换的开销
页面太大会使页内碎片增多,降低内存的利用率
页表项的大小 = 块号长度 (即页框号长度,内存块号长度),由逻辑地址空间大小决定(或者物理内存空间大小)。当然,可以增加一些其他信息如有效位来调整页表项大小,使得一页可以正好容下整数个页表项。
页表项与地址结构的异同:第一部分都是页号(页表项省略了),第二部分页表项为页框号、地址结构为页内偏移。
勘误:最终物理地址为00000000000000001001000000000001
如果引入了请求式分页管理,即虚拟内存机制,则此时的地址称为虚拟地址,虚拟地址的地址结构决定了虚拟内存的寻址空间有多大。
这里说逻辑结构有一点歧义,如果在有分段存储管理的情况下,在未经过分段翻译前的地址叫做逻辑地址,分段翻译后,未经分页翻译前的地址叫做线性地址(虚拟地址)。
如果没有分段存储管理,此时未经分页翻译的地址就既叫做线性地址,也叫逻辑地址,也叫虚拟地址。
基本地址变换机构
访存两次,第一次访问页表(假设页表全部调入内存),第二次访问物理地址
页表保存在内存中,其始址保存在PCB中,当进程调度运行时,PCB中的始址会放到页表机制寄存器中。
分页其实就是将连续的线性地址,平均分成页,将每页调入分配到离散的页框上。
TLB的作用就是将两次访存大概率地转换为一次访存。
多级页表
王道原话:“由于引入了分页管理,进程在执行时不需要将所有页调入内存页框(请求分页方式),而只需将保存有映射关系的页表调入内存。但页表必须连续存放(才能支持逻辑地址结构的快速转换)。所以对于只需要几个页面调入内存页框就能执行的进程来说,其页表可能比调入的页面还要大的多(而且很多页表项其实不太用的到)。”
分页存储下,连续的线性地址被分成页面大小,32位逻辑地址空间被分成220 个4KB的页面。所以页表需要2204B=4MB的空间来存储,需要210个页面。
但是注意这220 个4KB的页面同样是连续存储的,所以我们再将其分成210个小组,每组有210个页面。这样顶层页表就只需要存储小组信息,顶级页表需要2104B=4KB来存储(正好是一个页面,为了查询方便,规定顶层页表最多只能有一个页面)。第二级虽然还是需要2102104B=4MB的空间来存储,但是不需要全部调入,只需要调入要用的就可以(请求分页方式、缺页中断),所以节省了内存空间。因为顶层页表最多只能占一个页面,总共可以容纳4KB(页面大小)/4B(页表项大小)= 1K个页表项,所以地址结构中页号(共20位)里剩下的位数就是二级页表的页表项数目,正好也是10位,使得二级页表的大小也在一页之内。
基本分段存储管理
段表项48位 = 0位(段号)+ 16位(段长)+ 32位(基址=物理地址)
基本地址变换机构
分页与分段对比
分页存储 按照页大小划分逻辑地址空间 页内连续、页间也连续,由页表映射关系将页映射到页框
分段存储 按照自然段划分逻辑地址空间 段内连续、段间不连续,由段表映射关系将段映射到内存中连续的一片区域
分页和分段都需要判断页号或段号是否越界,而分段还需要判断段内偏移是否越界(因为段内偏移是程序员指定的),分页不需要判断业内偏移是否越界(因为页内偏移是算出来的,不可能越界)。
段页式管理
在这里 段表其实充当了页表寄存器的角色:提供了页表实址和页表长度
虚拟内存
虚拟存储器特点:
- 多次性:多次调入
- 对换性:换入换出
- 虚拟性:逻辑上扩充(结果)
除了要有页表机制和地址变换机构外,还需要 中断机构的介入
局部性原理
时间局部性:在一段时间内,某一条指令被多次执行、某一段数据可能被多次访问。(因为程序中存在大量的循环操作)
空间局部性:在一段时间内,程序访问的地址可能集中在一定范围内。(因为指令通常是顺序存放、顺序执行的。数据也一般是以向量、数组、表等形式簇聚存储的)时间局部性通过将近来使用的指令和数据备份到高速缓存中,并使用高速缓存的层次结构实现。
空间局部性通过使用较大的高速缓存,并将预取机制集成到高速缓存控制逻辑中实现。
虚拟内存利用局部性原理建立了“内存-外存”的两级结构。
请求分页管理方式
页面置换算法
页框分配
采用固定分配策略时,可采用以下算法将系统中的空闲物理块分配给进程:
- 平均分配算法
- 按比例分配算法:根据进程大小按比例分配
- 优先权分配算法:把可分配的物理块分为两部分——一部分按比例分配给各进程,一部分根据优先级分配