目录
8.1 背景
8.1.1 基本硬件
-
程序应被调入内存放入进程后才能被执行;
-
CPU能直接访问的存储器只有内存和寄存器;
-
寄存器能在一个CPU时钟内完成访存;
-
内存可能需要多个CPU时钟;
-
Cache在内存和CPU寄存器之间;
-
存储保护需要确保操作的正确性:
-
每个进程都有一个单独的地址空间;单独进程内存空间可以保护互不受影响;
-
要确定一个进程合法的地址访问空间范围;并确保访问的地址是合法的;
-
通过两个寄存去,分别为基地址寄存器和界限地址寄存器;
-
内存地址保护是通过CPU硬件对用户模式下产生的地址与两个寄存器地址比较得到的;
-
只有内核通过特权指令可以访问两个寄存器;
-
8.1.2 地址绑定
-
程序作为二进制的可执行文件放在磁盘上;
-
为了执行某个程序,必须将程序调入内存并放入进程;
-
在磁盘上等待调到内存以便执行的进程形成了输入队列;
-
(内存管理方案)进程在执行前经历了很多步骤对其地址空间实现映射转换,最终转换为实际的存储空间的绝对地址:源地址通常用符号表示,编译器将这些符号绑定到可重定向的地址;连接程序或加载程序再将这些可重定向的地址绑定到绝对地址;
-
指令和数据绑定带绝对地址(存储器地址)可能在沿途中间一步就完成了:
(1)编译时:如果直接指导存储器地址,则生成绝对代码;否则,重定向代码;
(2)加载时:对编译产生的可重定向代码绑定到绝对地址上;
(3)执行时;
8.1.3 逻辑地址空间与物理地址空间
-
逻辑地址vs物理地址
-
逻辑地址是CPU产生的地址
-
物理地址是内存看到的地址,通常是加载到内存地址寄存器中的地址MAR;
-
-
逻辑地址和物理地址的产生:
-
编译和加载时的地址绑定方法生成相同的逻辑地址和物理地址;
-
执行时的地址绑定方法生成不同的逻辑地址和物理地址;
-
-
逻辑地址到物理地址,运行时的映射是由内存管理单元MMU的硬件设计来实现的;
8.1.4 动态加载
【动态加载的定义】:一个程序只有被调用的时候才会被加载;
每个程序一重定向的格式被保存在磁盘上;
运行时,只将主程序装入内存;
当调用某程序段时,调用程序检查该程序是否已经装入内存,如果已经装入则直接调用;如果未装入内存,则通过可重定向链接程序将该程序段掉入内存,更新程序的地址表,控制传递给新的程序;
【优点】:节省了内存空间;支持虚拟存储;
【缺点】:管理复杂,运行速度降低;
【绝对加载的定义】:运行时装入所有模块;
8.1.5 动态链接与共享库
【动态链接的定义】:动态链接和动态加载相似,动态加载是将加载的过程延迟到执行,动态链接是将连接过程延迟到执行;
【动态链接的优点】:节省空间;减少链接所用的时间;便于模块的升级和共享;
【共享库和存根的定义】:
「存根」:如果使用动态链接,在二进制映像内,每个库程序的引用都有一个存根;
「存根的作用机制」:存根用来指出如何定位内存驻留库程序,或该程序不在内存中时,如何加载库;
「存根的作用过程」:当执行程序时,需要链接该程序调用的库程序时,执行该库程序的存根,存根检查该库函数是否已经在内存中;如果不在通过存根定位到磁盘将库程序加入内存中;如果检查在内存中,则用程序地址来替换自身,并开始执行;因此,下次执行该程序代码就可以直接执行,不需要任何链接的开销;
8.2 交换
【交换的定义】:进程可以暂时从内存中交换到备份存储(backing store)中,当再次执行时再调回内存,增加了系统的多道程序程度;
8.3 连续内存分配
内存通常分成两个区域,一个用于驻留操作系统(低内存区),一个用于用户进程;需要将多个程序同时放入内存中,因此需要考虑如何为输入队列中的程序分配内存空间;
8.3.1 内存保护
CPU硬件产生用户模式下的地址,进入操作系统内核调用特权指令,对该地址进行内存检查,通过界限地址寄存器判断范围是否越界;然后通过重定向寄存器MMU产生物理地址给内存;
8.3.2 内存分配
-
内存分配的两个方案:
【固定分区大小的多分区】:每个进程放入一个分区;多道程序程度决定于分区数;批处理系统和纯分段内存管理的分时操作系统;
【可变分区】:
「定义」:
表:系统为一张表,记录内存哪些已分配哪些还能用;
孔:可以作为一大块内存可用的称为孔,可分配、释放、合并;
分区方案:通用动态存储分配问题;
「孔分配的方案」:
首次适应(性能优秀、速度快)、最佳适应(性能优秀)、最差适应
8.3.3 碎片(fragmentation)
-
外部碎片
【发生情况】首次适应和最佳适应算法
【定义】随着进程的装入会让移出内存,空闲内存被分成小分段;
【外碎片问题】当所有总攻的空闲区大小满足当前进程装入请求,但不连续,就出现了外碎片的问题;
【产生影响因素】首次适应最佳适应的选择、空闲块从哪一端开始分配、内存大小、平均进程大小有关;
【解决方法】
「方法一」紧缩
(1)机制:动内存内容,以便将空闲空间和成一片,方便分配;
(2)使用范围:重定向是动态的,并且在运行时的可以采用紧缩;
(3)实施:移动程序和数据,然后根据新的基址地址更改寄存器中的值去更新基地址寄存器;
(4)缺点:开销大;
「方法二」允许物理地址非连续
(1)机制:有物理内存就可以进行分配;
(2)实现技术:分页和分段;或两个合并;(分页产生内碎片、分段产生外碎片)
-
内部碎片
【定义】当内存分配采用固定大小分区进行分配,进程所分配的内存大小可能大于需要的空间大小,二者差值就会产生碎片;
8.4 分页(paging)
8.4.1 基本方法
-
分页的前提:允许进程的物理地址是不连续的;
-
分页支持:硬件支持,操作系统和硬件支持;
-
基本方法:帧、页、页表、备份存储、逻辑地址组成、物理地址组成;
-
进程调用的机制:当进程被调用时,CPU产生的对应代码段的逻辑地址,根据洛基地址转化为物理地址,将该逻辑地址对应的代码段从备份存储中取出放入内存中物理地址对应的位置;再将逻辑地址和物理地址对应的方式写入页表;
-
分页的特点:
(1)碎片:不产生外部碎片,但是会产生页内部的内部碎片;
(2)重要特征:用户视角的内存和实际的物理内存的分离;用户视角中,内存是一整块的且只包含一个进程;而实际上物理内存分页,且同时保存多个进程;
(3)页表机制使上下文切换增加时间,因为每个进程保存一个页表副本;当进程被调用时,将页表副本作为上下文切换中的一项任务,因此增加了上下文切换的时间;
-
帧表:操作系统维护一张帧表,该表中记录每帧物理内存是否空闲,如果不空闲,记录是被哪个进程的哪个页所占用;
8.4.2 硬件支持
-
页表的设置:
每个进程都有一个页表,该页表设置包含了进程的每个页在内存中的位置;如果能将每个进程的页表均放入专门的寄存器中,查询调用速度会很快,但是因为空间限制,大部分进程的页表还是在内存中;
当该进程未被执行时,该进程的页表别放在内存中,页表的信息(PTBR、PTLR页表的始址和页表长度)一直存放在该进程的PCB中(此时该进程的内容所有内容代码段数据段PCB等内存中);
当进程被执行时,将该进程的PCB中页表始址和页表长度的放入MMU的响应的两个页表寄存器中;
CPU执行进程产生逻辑地址送入MMU,MMU根据两个值去物理内存找到页表后,对CPU产生的地址进行安全检测和物理地址产生;
-
页表设置的问题:每次CPU产生的逻辑地址的页表号还要加上页表始址去内存中找到页表号对应的帧号;访存需要时间;
-
问题的解决:TLB转换表缓冲区;
-
TLB原理:将在内存中的页表项(注意不是某个进程的一整个页表)放入一个专门的页表行cache;TLB每一项包含属性地址空间唯一标识ASID(用于表示该页表项属于哪个进程)、页号、帧号;
-
TLB中的ASID允许TLB包含多个进程的页表项,这样每次切换进程时就不用对TLB进程删除刷新,不用进行上下文切换;
8.4.3 保护
两个保护措施:有效无效位、读写权限位
【读写权限位】:页表中设置一个属性——读写权限位,来限制该进程对该页表是可进行读写还是只能进行读;
【有效无效位】:页表中设置一个属性——有效无效位,来表示该进程的该页表项是否属于该进程的有效抵制范围内的;(或者将段号和段长度进行比较,以检测段号是否越界)
「为什么会有有效无效位的概念」:因为该进程的页表中包含了不属于该进程的页;
「有效位页表项无效的问题」:对于最后一个有效页,该页中也有部分地址是无效的,这些地址空间属于页内碎片;
【虽然存在有效无效位还是要通过PTLR进行地址越界判断】
8.4.4 共享页
-
共享页的机制:代码段在内存中分野存储,多个进程可以对该代码代码段页项加入自己的页表中实现共享;
-
页共享的条件:
【共享代码段必须是可重入代码或者纯代码】
-
含有static的函数不能共享,因为不是纯代码;(这样的代码不具有自身修改性,被共享的代码只读访问)
-
共享代码段在所有共享程序中的逻辑地址空间中的位置必须相同;(页号相同、页内偏移量也相同)
-
-
共享的进程有自己独有的代码和数据;
8.5 页表结构
「为什么需要页表结构」:开玩笑一样的,开始的时候说页表可以存在寄存器中,后来说寄存器中装不下页表,需要装在内存了,结果现在说这个玩意儿实在太大,在内存里还要分页存储,因为一帧都装不下这个页表;还得分散了不连续地装;所以搁这儿,页表里的页表项还得有个映射的表(页表的页表)记录页表在哪个帧中;所以才有了页表项与帧的映射关系;
8.5.1 分层页表
分两层或多层——计算题
8.5.2 哈希页表
CPU 产生的逻辑地址的页号给哈希函数,哈希函数定位到该页号对应的桶中,在桶中寻找该页号,根据找到的项定位到内存物理地址;
就是将大量的页表项通过哈希函数放入不同的桶中方便查找;
8.5.3 倒置页表
页表项每一项代表一个帧,包含内存中该帧对应的存放的进程代码对应的进程号和代码所处页号;因此每次查找的项在页表中的位置就是所在帧号;
8.6 分段
8.6.1 分段概念
(基本组成和分页差不多)
「分段和分页的区别」
(1)页是信息的物理单位,实现离散分配;是为了消除外碎片,仅用于内存管理;
(2)段是信息的逻辑单位,包含一组意义完整的信息;是为了满足用户的需求;
(3)页大小固定,系统决定;段长度不固定,用户编写的程序决定;
(4)分页作业地址空间是一维的,分段二维因为有段名+段内地址;
8.6.2 硬件支持
(同分页)
补充:段页式
「思想」:作业们先分段,每个段内在分页;一个作业对应一个段表,一个段对应一个页表;页是内存分配的单位;
思考:
-
思考 Page 310 8,10,11,14
-
思考题 几个地址及相应的地址空间概念; 静态链接与动态链接 静态装入与动态装入 分区管理中的几个分区算法; Fragmentation 分页、分段管理的基本思想; 分页、分段管理的地址变换过程;变换工作中硬件与软件的分工。 分页、分段管理的存储保护方法; 分页、分段管理的内存共享(方法、条件) Structure of the Page Table(页表结构)
-
Page 310 1,3,4,5,6,9,12,13