最近开始学习操作系统原理这门课程,特将学习笔记整理成技术博客的形式发表,希望能给大家的操作系统学习带来帮助。同时盼望大家能对文章评论,大家一起多多交流,共同进步!
本文主要分以下几个方面:
- Demand Paging 请求分页
- Page Replacement 页面置换
- Allocation of Frames 页框分配
- Thrashing 抖动(缺点)
背景:
Virtual Memory:
- 逻辑存储和物理存储分开
- 只有一部分程序在内存中
- 逻辑地址空间 >= 物理地址空间
在很多情况下,程序是不需要一定常驻内存的:
- Error code
- Arrays, lists, & tables allocated more than need
- Certain options & features of a program rarely used
优点:
- 程序可远远大于分配的物理内存
- 支持更多程序直接运行
- 程序员不需担心内存限制
- 较小的I/O需求,每一个用户程序会响应的更快
- 简单的在多进程中实现文件共享
- 进程创建的效率更高
缺点:
- 抖动,页面置换 => extra overhead
尽量将缺点降到最低。
Demand Paging 请求分页
- 使用请调(需要时才调入)的方式将页面调入内存
- 较小的I/O需求
- 较小的内存需求
- 更快的响应
- 支持更多用户
Lazy swapper 懒惰交换
- 只有页面要用时才将其装入内存 - 纯请调
- 页面的装载程序称作paper
预调:一种优化手段,使得某些页面的第一次调用不会发生缺页(page fault)
页表的数据结构:页号-页框号-有效位(Valid-Invalid bit)
对页表的所有选项都存在于有效-无效位:
- 初始化均为i
- v => 在内存且合法
- i => 不在内存中 => 访问时发生缺页(page fault)
- 根本不存在该页表:终止
- 不在内存中但可在外存中访问到:放入内存
因此页表数据结构还需加上访问位(reference bit),修改位(dirty bit),外存地址,保护位
修改位:指示该页面放入内存后是否被修改,即与外存中的副本是否相同,当修改才在退出内存的时候存放入外存中
当某些页面不在主存中的页表情况:
页面缺失(Page fault):首次访问某个页面引起的系统自陷(trap to OS)
- 无效访问:终止
- 有效访问但不在内存:
- Find a free frame (from the free frame list) 寻找空闲页框
- Swap page into frame 将页面装入页框
- Reset page tables 重置页表
- Set validation bit = v 将有效位设置为v
- Restart the instruction that caused the page fault 重新启动产生自陷的指令,这条操作与普通中断不同之处为中断之后执行产生中断后的下一条指令,因一条指令可能产生多个缺页中断
页面请求的性能分析 Performance of Demand Paging
设缺页的可能性为 0 <= p <= 1,
- 若p=0,则无缺页
- 若p=1,则称纯页面请求
有效访问时间(Effective Access Time, EAT)
EAT = (1-p) * memory access + p * page fault time(page fault overhead + swap page out(optional) + swap page in + restart overhead)
若没有空闲页框,则操作系统进行页面置换操作。页面置换分为全局置换(高优先级进程剥夺低优先级进程页框)和局部置换(在进程内部分配的页框进行置换)
某一页面也可能被多次换入换出。
修改位(modify/dirty bit):可减小页面置换产生的系统开销 -- 只有修改过的页面能被写入磁盘。
页框分配算法和页面置换算法的好坏直接影响到页面请求的性能。
页面置换的步骤:
- 找到外存上所需换入页面的地址
- 找到空闲页框
-
- 若存在空闲页框,则使用该页框
- 若无空闲页框,则使用页面置换算法所选择的牺牲者页框(victim frame)
3. 将需要换入的页面放入新的空页框,更新页表
4. 重启进程(将进程放入就绪队列等待下一次调度)
页面置换算法(Page Replacement Algorithm)
原则:最低的缺页率
使用访问串。有三种算法:
- First-In-First-Out(FIFO) 会产生Belady's Anomaly(Belady 奇异):分配更多的页框却产生更多的缺页
- Optional Algorithm 最有算法:置换未来最久不被访问的页面,然而现实中我们无法预知未来情况,但为其他算法提供了优化标杆
- Least Recently Used(LRU) 最近最少被使用算法:可使用计数器实现和栈实现
LRU近似算法
访问位:
- 硬件与每一个页面关联一个访问位,初始为0
- 访问后置为1
- 置换时寻找访问位为0的页面进行置换,然而当无访问位为0的页面则不知道页面访问的次序
额外的访问位算法:
- 每个页表表项关联一个8位的记录项
- 每一次缺页中断,则该项向右移一位,最高位置1
- 若缺页且无空白页面则对8位字节比大小,选择最小的数对应的页面进行置换
二次机会:
- 需要访问位(1 bit)
- 时钟值,最后被访问
- 将页面按照时间从远到近排列,选择访问位为0进行置换
- 若访问位为1:
- 将访问位设为0
- 留在内存
- 置换下一个页面
4. 计数算法 Counting
设一个每个页面被访问次数的计数器
LFU算法:
- 置换计数值最小的页面
- 问题:在系统初始化的时候调用频繁,然后就不会在调用,可将计数器的值右移一位来减小使用计数值
MFU算法:
- 计数值最小的页面可能刚被放入内存并即将被使用
页框分配:进程需要页面的最小分配数,即需要执行一个指令所需访问的所有页面
- 固定页框分配
1. 平等分配
2. 比例分配:按进程大小进行比例分配
- 优先级分配:按进程优先级成比例分配
若进程Pi产生缺页中断,则可选择该进程本身或优先级较低的进程(全局)的页框进行置换。
全局置换:优点:页框使用率高;缺点:某些进程可能被频繁剥夺内存资源
局部置换:优缺点与全局置换相反
抖动 Threshing
如果一个进程没有足够的页面,则:
- 缺页率提高
- 低CPU利用率
- os认为需提高道数
- 另一个进程被加入系统,造成恶性正反馈
抖动:进程一直忙于页面的换入换出,置换页面的时间高于CPU执行的时间
解除抖动需引入局部模型:进程从一个局部到另一个局部,一个进程有N个局部,可能产生重叠
当∑size of locality > total memory size => Active pages > frames allocated , 发生抖动
工作集 Working-Set Model
∆:工作集窗口数,活动页面,一个固定的页面访问数
若∆过小 => 不能包含一整个工作集
若∆过大 => 可能包含多个工作集
若∆=无穷大 => 包含整个程序的工作集
记录工作集模型:近似处理方式:时钟中断器+访问位,每一次中断将在内存中的页面访问位置1,将不在内存中的访问位置0.