3 内存
3.1 基础知识
存储单元
内存存放数据,程序执行之前先放到内存中才能被内存处理
210=1K,220=1M,230=1G
进程运行基本原理
指令工作原理:操作码+若干参数或包含地址参数
代码翻译为指令,指令通知CPU去内存地址对数据做怎样的处理
逻辑地址:相对地址
物理地址:绝对地址
程序编译将源代码编译成若干个目标模块->链接程序链接库函数形成装入模块->装入装入程序将装入模块装入内存运行
装入的三种方式
- 装入模块指令地址为相对地址,在装入内存时需要将其转换为物理地址
- 绝对装入:编译时知道程序放入内存的位置,编译程序将直接产生绝对地址的伪代码
- 静态重定位:编译链接后装入模块地址从0开始,模块使用的地址数据存放地址是相对起始地址而言的逻辑地址,根据内存情况装入内存,并在装入时对地址进行重定位一个作业装入时必须分配全部内存空间
- 动态重定位:装入后不会立即转换为物理地址,而是在程序执行时进行地址转换可以将程序分配到不连续的存储区中,允许程序在内存中发生移动
链接的三种方式
静态链接:程序运行之前就将目标模块与库函数链接成完整地可执行文件
装入时动态链接:目标模块装入内存时,边装入边链接
动态运行时装入:目标执行需要该目标模块时,才对其进行链接
3.2 内存管理
操作系统负责内存空间的分配和回收,并提供某种技术从逻辑上对内存空间进行扩充,并提供地址转换功和内存保护功能
内存保护:
- CPU设置上下限寄存器,存放进程的上下限地址并由CPU在进程访问地址时进行检查
- 重定位寄存器基址寄存器(存放进程起始物理地址)和界地址寄存器限长寄存器(存放进程最大逻辑地址)
覆盖技术
将程序分为多个段,常用段常驻,不常用段在需要时调入
内存分为一个固定区常驻的段调入和若干个覆盖区不常用的段,用时调入不用时调出
交换技术
内存空间紧张时,系统将内存中某些进程暂时换出外存 挂起状态:就绪挂起或阻塞挂起,把某些已具备运行条件的进程换入内存 进程在内存和磁盘之间动态调度
磁盘存储空间可被具有对换功能的操作系统分为对换区 存储换出来的进程数据,只占一小部分和文件区
虚拟内存
内存分配与回收
连续分配管理方式
单一连续分配方式
内存中只能有一道用户程序,用户程序独占整个用户空间
优点:实现简单无外部碎片内存中某些空闲分区由于太小难以利用,可以使用覆盖技术
缺点:智能用于单用户单任务的操作系统,有内部碎片分配进程的内存区域中有些部分没用上
固定分区分配
用户空间划分为若干个固定大小的分区,
分区大小一样:灵活性差,适用于一台计算机控制多个相同对象的场合
分区大小不等:增加灵活性
动态分区分配
不预先划分内存分区,根据进程大小动态的建立分区
如果使用空闲分区表这种数据结构
无内部碎片,有外部碎片(可通过紧凑技术解决)
回收内存分区时,相邻的空闲分区要合并
动态分区分配算法
首次适应算法
算法思想:每次从低地址开始找,找到第一个能满足大小的空闲分区
实现:空闲分区按地址递增的次序排列
最佳适应算法
算法思想:尽可能留下大片空间,尽可能先使用更小的空闲区
实现:空闲分区按容量递增次序链接
最坏适应算法
算法思想:解决最佳适应算法留下太多难以利用小碎片的问题
实现:空闲分区按容量递减次序链接
缺点:导致大分区被迅速占用
邻近适应算法
算法思想:每次检查时从上次查找结束的地方开始查找
实现:空闲分区按地址递增顺序排列,分配内存时从上次查找结束的位置开始
缺点:会使高地址的大分区被用完
非连续分配管理方式
分页存储
将内存空间分配为一个个大小相等的分区,每个分区是一个页框,对应一个编号 页框号,从0开始,将进程的逻辑地址空间分为与页框大小相等的部分,每个部分称为一个页或页面
页框=页帧=内存块=物理块=物理界面
页框号=页帧号=内存块号=物理块号=物理界面号
页表——重要的数据结构:用于存放进程的每个页面在内存中存放的位置
地址转换:找到逻辑地址A对应页号,找到该页号的起始地址,确定逻辑地址A的页内偏移量
基本地址变换机构:
页表项长度:每个页表项占多大存储空间
页表长度:该页表总共几个页表项
页面大小:一个页面占多大存储空间
快表的地址变换结构
快表:联想寄存器TLB,访问速度比内存快很多的高速缓冲寄存器内存中的页表常称为慢表
①CPU给出逻辑地址,由某个硬件算得页号、页内偏移量,将页号与快表中的所有页号进行比较。
②如果找到匹配的页号,说明要访问的页表项在快表中有副本,则直接从中取出该页对应的内存块
号,再将内存块号与页内偏移量拼接形成物理地址,最后,访问该物理地址对应的内存单元。因此,
若快表命中,则访问某个逻辑地址仅需一次访存即可。
③如果没有找到匹配的页号,则需要访问内存中的页表,找到对应页表项,得到页面存放的内存块
号,再将内存块号与页内偏移量拼接形成物理地址,最后,访问该物理地址对应的内存单元。因此,
若快表未命中,则访问某个逻辑地址需要两次访存(注意:在找到页表项后,应同时将其存入快表,
以便后面可能的再次访问。但若快表已满,则必须按照一定的算法对旧的页表项进行替换)
局部性原理
时间局部性:如果执行了程序中的某条指令,那么不久后这条指令很有可能再次执行;如果某个数据被访问过,不久之后该数据很可能再
次被访问。( 因为程序中存在大量的循环)
空间局部性: - -旦程序访问了某个存储单元,在不久之后,其附近的存储单元也很有可能被访问。(因为很多数据在内存中都是连续存放
的)
两级页表
二级页表地址转换:
①按照地址结构将逻辑地址拆分成三部分
②从PCB中读出页目录表始址,再根据一级页号查页目录表,找到下一级页表在内存中的存放位置.
③根据二级页号查表,找到最终想访问的内存块号
④结合页内偏移量得到物理地址
多级页表机制时,各级页表的大小不能超过一个页面
N级页表访问一个逻辑地址需要N+1次访存
缺页中断
没必要让整个页表常驻内存,进程在一段时间秩序访问某几个特定页面,所以将其他页表调入外存,当访问发现需要访问的页面不在内存,产生缺页中断内中断,然后将目标页面从外存调入内存
分段存储管理
进程的地址空间按照程序自身的逻辑关系划分为若干个段,每个段都有一个段名( 在低级语言中,程序员使用段名来编程),每段从0开始编址
内存分配规则:以段为单位进行分配,每个段在内存中占据连续空间,但各段之间可以不相邻。
段号位数决定进程最多可以分多少个段
段内地址决定了每个段的最大长度
段表
比页表多了个段长
相对于分页,在查询段表后要对段内地址进行检查,检查段内地址是否超过段长
分段与分页的区别
分页 | 分段 | |
---|---|---|
页是信息的物理单位。分页的主要目的是为了实现离散分配,提高内存利用率,分页仅仅是系统管理上的需要,完全是系统行为,对用户是不可见的 | 段是信息的逻辑单位。分段的主要目的是更好地满足用户需求。个段通常包含着一组属于一个逻辑模块的信息。分段对用户是可见的,用户编程时需要显式地给出段名 | |
大小 | 固定,由系统决定 | 长度不固定,取决于用户程序 |
用户进程的地址空间 | 一维,标识地址只需给出一个记忆符 | 二维,标识地址时既需要给出段名,也需要给出段内地址 |
信息保护 | 分段比分页更容易实现信息的共享和保护。不能被修改的代码称为纯代码或可重入代码(不属于临界资源),这样的代码是可以共享的。可修改的代码是不能共享的 | |
访存次数 | 分页(单级页表) :第一次访存–查内存中的页表,第二次访存-- -访问目标内存单元。总共两次访存. | 分段:第一次访存–查内存中的段表,第二次访存–访问目标内存单元。总共两次访存与分页系统类似,分段系统中也可以引入快表机构,将近期访问过的段表项放到快表中,这样可以少一次访问,加快地址变换速度。 |
段页式管理
将进程按逻辑模块分段,再将各段分页
每个段对应一个段表项:段号、页表长度、页表存放块号组成
地址转换
3.3虚拟内存
基于局部性原理,将程序中很快要用到的部分装入内存,暂时用不到的部分留在外存,执行时需要用到时再由操作系统将所需信息调入内存,内存空间不够时,由操作系统将内存中暂时不用放入信息换出到外存 在这种情况下,内存看起来比实际大得多,这就是虚拟内存
特性:多次性、对换性。虚拟性
虚拟内存建立在离散分配的基础上
虚拟内存实现方式:在程序执行过程中,当所访问的信息不在内存时,由操作系统负责将所需信息从外存调入内存,然后继续执行程序请求调页。若内存空间不够,由操作系统负责将内存中暂时用不到的信息换出到外存页面置换。
1. 请求分段存储管理
2. 请求分页存储管理‘
3. 请求段页式存储管理
请求分页存储管理
页表机制
缺页中端机构
在请求分页系统中,每当要访问的页面不在内存时,便产生一个缺页中断,然后由操作系统的缺页中断处理程序处理中断。
此时缺页的进程阻塞,放入阻塞队列,调页完成后再将其唤醒,放回就绪队列。
如果内存中有空闲块,则为进程分配一个空闲块,将所缺页面装入该块,并修改页表中相应的页表项。
如果内存中没有空闲块,则由页面置换算法选择一个页面淘汰,若该页面在内存期间被修改过,则要将其写回外存。未修改过的页面不用写回外存。
地址变换机构
页面置换算法
算法规则 | 优缺点 | |
---|---|---|
OPT最佳置换算法 | 优先淘汰最长时间内不会被访问的页面 | 缺页率最小,性能最好;但无法实现 |
FIFO 先进先出置换算法 | 优先淘汰最先进入内存的页面 | 实现简单;但性能很差,可能出现Belady异常 |
LRU最近最久未使用置换算法 | 优先淘汰最近最久没访问的页面 | 优先淘汰最近最久没访问的页面 |
CLOCK ( NRU)时钟置换算法 | 循环扫描各页面第一轮淘汰访问位=0的在此之前,如果为1则改为0,并将扫描过的页面访问位改为1。若第一轮没选中,则进行第二轮扫描。 | 实现简单,算法开销小;但未考虑页面是否被修改过。 |
改进型的时钟置换算法 | 若用(访问位,修改位)的形式表述,则 第一轮:淘汰(0,0) 第二轮:淘汰(0,1),并将扫描过的页面访问位 都置为0 第三轮:淘汰(0,0) 第四轮:淘汰(0, 1) | 算法开销较小,性能也不错 |
belady异常:当为进程分配的物理块数增大时,缺页次数不减反增的异常现象只有FIFO算法会产生 |
改进时钟实际上优先级递减(0,0)最近没访问也没修改,(0,1)最近没访问但修改过,(1,0)最近访问过但没修改,(1,1)最近访问过也修改过
页面分配策略
驻留集:请求分页存储管理中给进程分配的物理块的集合
在采用了虚拟存储技术的系统中,驻留集大小- -般小于进程的总大小。
若驻留集太小,会导致缺页频繁,系统要花大量的时间来处理缺页,实际用于进程推进的时间很少;
驻留集太大,又会导致多道程序并发度下降,资源利用率降低。所以应该选择一个合适的驻留集大小。
固定分配:操作系统为每个进程分配一组固定数目的物理块,在进程运行期间不再改变。即,驻留集大小不变
可变分配:先为每个进程分配一定数目的物理块,在进程运行期间,可根据情况做适当的增加或减少。即,驻留集大小可变
局部置换:发生缺页时只能选进程自己的物理块进行置换。
全局置换:可以将操作系统保留的空闲物理块分配给缺页进程,也可以将别的进程持有的物理块置换到外存,再分配给缺页进程。
固定分配局部置换:系统为每个进程分配一定数量的物理块,在整个运行期间都不改变。若进程在行中发生缺页,则只能从该进程在内存中的页面中选出一页换出,然后再调入需要的页面。这种策的缺点是:很难在刚开始就确定应为每个进程分配多少个物理块才算合理。(采用这种 策略的系统以根据进程大小、优先级、或是根据程序员给出的参数来确定为一个进程分配的内存块数)
可变分配全局置换:刚开始会为每个进程分配一定数量的物理块。操作系统会保持一个空闲物理块列。当某进程发生缺页时,从空闲物理块中取出一块分配给该进程;若已无空闲物理块,则可选择个未锁定的页面换出外存,再将该物理块分配给缺页的进程。采用这种策略时,只要某进程发生缺都将获得新的物理块,仅当空闲物理块用完时,系统才选择一个未锁定的页面调出。被选择调出的
可能是系统中任何一个进程中的页,因此这个被选中的进程拥有的物理块会减少,缺页率会增加。
可变分配局部置换:刚开始会为每个进程分配一 定数量的物理块。当某进程发生缺页时,只允许从进程自己的物理块中选出一一个进行换出外存。如果进程在运行中频繁地缺页,系统会为该进程多分几个物理块,直至该进程缺页率趋势适当程度;反之,如果进程在运行中缺页率特别低,则可适当少分配给该进程的物理块。
调入页面时机:
- 预调页策略:主要用于进程的首次调入
- 请求调页测流:运行时调入
工作集
抖动(颠簸)现象
刚换出页面又要换入内存,刚换入的页面又要换出外存主要原因是驻留集太小
工作集:某段时间间隔里,进程实际访问页面的集合一般驻留集要大于工作集
内存映射文件
操作系统向上层程序员提供的功能(系统调用)
以访问内存的方式访问文件数据文件数据的读入、写出由操作系统自动完成
进程关闭文件时,操作系统自动将文件被修改的数据写回磁盘