0 00:00:00,000 --> 00:00:06,800 1 00:00:07,000 --> 00:00:10,920 接下来我们介绍缺页异常 2 00:00:11,000 --> 00:00:12,560 那么缺页异常呢 3 00:00:12,600 --> 00:00:15,360 在我们前面讲页式存储管理里说 4 00:00:15,400 --> 00:00:19,560 缺页异常就是发现页表项当中这一页 5 00:00:19,600 --> 00:00:22,560 不在物理内存当中我就会产生缺页异常 6 00:00:22,600 --> 00:00:25,520 缺页异常把相应的内容读到内存里头来 7 00:00:25,560 --> 00:00:27,320 我再重新执行这条指令 8 00:00:27,360 --> 00:00:29,640 这是我们前面对缺页异常的描述 9 00:00:29,680 --> 00:00:31,640 那实际上在缺页异常里头呢 10 00:00:31,680 --> 00:00:33,200 还有很多要处理的内容 11 00:00:33,240 --> 00:00:36,960 我们现在先来介绍一下缺页异常的处理流程 12 00:00:37,000 --> 00:00:40,320 那在这儿我们现在有一个图来说明这个过程 13 00:00:40,360 --> 00:00:44,080 首先是我在CPU里头呢要访问一条指令 14 00:00:44,120 --> 00:00:45,880 比如说load M 15 00:00:45,920 --> 00:00:49,560 这条指令呢它会找m所对应的页表项 16 00:00:49,600 --> 00:00:53,400 找到这一项之后 如果这一项是有效的 17 00:00:53,440 --> 00:00:56,000 那这时候呢或者是驻留位是为1 18 00:00:56,040 --> 00:00:58,320 好 这时候它就直接去访问去了 19 00:00:58,360 --> 00:01:00,640 如果这一页是无效的 20 00:01:00,680 --> 00:01:02,600 那这时候就会产生缺页异常 21 00:01:02,640 --> 00:01:06,720 缺页异常呢就会导致操作系统的 22 00:01:06,760 --> 00:01:09,440 缺页异常服务例程的执行 23 00:01:09,480 --> 00:01:12,120 这个缺页异常服务例程它干什么呢 24 00:01:12,160 --> 00:01:14,600 它缺页之后那首先第一个它得找到 25 00:01:14,640 --> 00:01:19,040 对应着那一页在外存当中存在什么地方 26 00:01:19,080 --> 00:01:21,120 如果说有这一页之后找到了 27 00:01:21,160 --> 00:01:23,240 那这时候呢我把这一页读到内存里头来 28 00:01:23,280 --> 00:01:25,280 读到内存里头来就会带来一个问题 29 00:01:25,320 --> 00:01:27,800 我在内存里我到哪去找这一页 30 00:01:27,840 --> 00:01:29,560 我肯定要找空闲的页面 31 00:01:29,600 --> 00:01:32,600 如果找着那这时候呢我把这一页读进来 32 00:01:32,640 --> 00:01:37,160 并且回身要修改相应的页表项 33 00:01:37,200 --> 00:01:39,040 那页表项修改 34 00:01:39,080 --> 00:01:42,800 修改完了之后然后我再重新执行这条指令 35 00:01:42,840 --> 00:01:46,560 OK 这样以来的话 我这个缺页异常呢 36 00:01:46,600 --> 00:01:49,480 就算是 大致的流程就算处理完了 37 00:01:49,520 --> 00:01:51,880 但是在这个过程当中如果说 38 00:01:51,920 --> 00:01:54,360 这个你要找空闲页找不着 39 00:01:54,400 --> 00:01:55,360 那这时候怎么办呢 40 00:01:55,400 --> 00:01:57,120 那这时候我们还需要把这个流程 41 00:01:57,160 --> 00:02:00,360 再对这一段呢再做一个细化 42 00:02:00,400 --> 00:02:01,600 那也就是我们这边说的 43 00:02:01,640 --> 00:02:03,560 说我缺页异常我要在这里 44 00:02:03,600 --> 00:02:06,080 要去找空闲的物理页面 45 00:02:06,120 --> 00:02:08,640 如果能找着那这事没问题了 46 00:02:08,680 --> 00:02:11,280 直接蹦到我们刚才说的复制 47 00:02:11,320 --> 00:02:14,400 说的后面一步 如果没找着呢 48 00:02:14,440 --> 00:02:17,560 那这时候我就得把另外一页把它写出去 49 00:02:17,600 --> 00:02:22,800 我根据页面置换算法来找 50 00:02:22,840 --> 00:02:25,560 找一页我不常用的我把它替换出去 51 00:02:25,600 --> 00:02:27,760 假定说这一页的物理页帧号是F 52 00:02:27,800 --> 00:02:29,800 它对应的逻辑页号是Q 53 00:02:29,840 --> 00:02:31,600 好 我就找到这一项 54 00:02:31,640 --> 00:02:33,840 那么找到这一项之后我把它淘汰掉 55 00:02:33,880 --> 00:02:35,960 这时候我又有一个要判断的 56 00:02:36,000 --> 00:02:38,560 这个Q对应的这一项是否修改过 57 00:02:38,600 --> 00:02:41,840 如果修改过那你直接把它扔掉是不行的 58 00:02:41,880 --> 00:02:45,160 我还必须把这一页呢写到外存当中去 59 00:02:45,200 --> 00:02:47,680 给它找另外一个地方把它写那儿去 60 00:02:47,720 --> 00:02:49,240 然后写完了之后呢 61 00:02:49,280 --> 00:02:50,800 这一项我就可以拿回来用了 62 00:02:50,840 --> 00:02:52,280 那在这之前呢还有一个事 63 00:02:52,320 --> 00:02:57,360 要修改这个Q所对应的页表项的内容 64 00:02:57,400 --> 00:02:59,200 把这一项置为是无效 65 00:02:59,240 --> 00:03:01,160 以便于你下次再来访问的时候 66 00:03:01,200 --> 00:03:02,880 这一项我已经分配给别人了 67 00:03:02,920 --> 00:03:05,560 好 那如果说这写完了之后 68 00:03:05,600 --> 00:03:09,160 那这时候E 就是我们刚才说到这儿 69 00:03:09,200 --> 00:03:12,720 也就相当于我这儿有了一个空闲的页帧了 70 00:03:12,760 --> 00:03:16,240 我把相应的这个P对应的这一页 71 00:03:16,280 --> 00:03:22,160 把它装到这里头来 然后这是我们这里说的五这一步 72 00:03:22,200 --> 00:03:25,640 修改P对应着的页表项的驻留位 73 00:03:25,680 --> 00:03:28,400 表示这一页我已经把它对到这儿来了 74 00:03:28,440 --> 00:03:32,360 好 然后这里的6对应这一步 75 00:03:32,400 --> 00:03:36,920 我重新执行产生缺页异常的这一条指令 76 00:03:36,960 --> 00:03:40,280 整个这个处理流程就算处理完了 77 00:03:40,320 --> 00:03:43,320 那么有了这些介绍之后呢 78 00:03:43,360 --> 00:03:46,080 我们说对这个缺页异常呢有一个了解 79 00:03:46,120 --> 00:03:48,880 但是如果说你和实际的操作系统代码当中 80 00:03:48,920 --> 00:03:54,000 缺页异常处理相比较这个流程仍然是非常简化 81 00:03:54,040 --> 00:03:57,200 那实际代码里头比这处理又要复杂一些 82 00:03:57,240 --> 00:04:00,640 这个希望大家再去看实际代码来逐步 83 00:04:00,680 --> 00:04:03,520 把这个过程细化和加以理解 84 00:04:03,560 --> 00:04:06,080 好 那接下来我们还有一个问题是说 85 00:04:06,120 --> 00:04:09,160 我们刚才把在外存里找的那一页 86 00:04:09,200 --> 00:04:11,680 外存那个地方我怎么去找它呢 87 00:04:11,720 --> 00:04:15,760 那这个时候我的外存保存这一页放在哪 88 00:04:15,800 --> 00:04:17,480 我必须很方便地找 89 00:04:17,520 --> 00:04:20,880 在我们现在的操作系统里呢有两种搞法 90 00:04:20,920 --> 00:04:22,320 一种搞法呢是说 91 00:04:22,360 --> 00:04:24,840 我直接做一个分区叫兑换区 92 00:04:24,880 --> 00:04:27,760 这在Linux Unix都是这么干的 93 00:04:27,800 --> 00:04:30,600 另一个呢 我是可以用一个文件来存这些东西 94 00:04:30,640 --> 00:04:32,640 在文件里头我采用特殊的格式 95 00:04:32,680 --> 00:04:33,960 来映射这些页面 96 00:04:34,000 --> 00:04:36,960 因为在这头我通常都是固定大小的页面 97 00:04:37,000 --> 00:04:41,560 所以它的文件可以针对这种做法来做优化 98 00:04:41,600 --> 00:04:44,960 好 这是我往哪放的事 99 00:04:45,000 --> 00:04:46,520 这时候是不是所有东西 100 00:04:46,560 --> 00:04:48,720 全放这里头呢也不是这样 101 00:04:48,760 --> 00:04:52,080 因为我们在外存当中的这些 102 00:04:52,120 --> 00:04:53,760 进程地址空间里的内容 103 00:04:53,800 --> 00:04:57,680 有一些是我可以放到这里头兑换区里头的 104 00:04:57,720 --> 00:05:00,240 而另外一些呢你比如说像我们这里说到 105 00:05:00,280 --> 00:05:03,560 可能选择另外这样两种 一种是代码 106 00:05:03,600 --> 00:05:06,160 我本来代码是在可执行文件里头的 107 00:05:06,200 --> 00:05:08,880 那如果说你生生给它另整一个地方 108 00:05:08,920 --> 00:05:11,160 去把它复制过去保存这是没必要的 109 00:05:11,200 --> 00:05:15,080 所以这时候代码是直接指向你的可执行文件 110 00:05:15,120 --> 00:05:19,240 而还有一些就是共享库 这些库呢 实际上 111 00:05:19,280 --> 00:05:23,120 也是它有相应的目标文件来存放 112 00:05:23,160 --> 00:05:26,040 这时候呢 你也没必要把它复制到这里头来 113 00:05:26,080 --> 00:05:29,280 因为这两项内容呢我们都是不去修改的 114 00:05:29,320 --> 00:05:32,640 好 其它的数据段 堆栈段那这些呢 115 00:05:32,680 --> 00:05:35,320 你都可以放到你的兑换区里头 116 00:05:35,360 --> 00:05:36,720 和兑换空间里头 117 00:05:36,760 --> 00:05:38,880 好 最后一个问题我们来讨论 118 00:05:38,920 --> 00:05:42,000 虚拟页式存储管理的性能 119 00:05:42,040 --> 00:05:44,240 我们如何来评价 120 00:05:44,280 --> 00:05:46,480 虚拟页式存储管理的性能呢 121 00:05:46,520 --> 00:05:48,480 在这呢我们定义了一个指标 122 00:05:48,520 --> 00:05:51,520 叫做有效存储访问时间 123 00:05:51,560 --> 00:05:53,480 这个有效存储访问时间呢 124 00:05:53,520 --> 00:05:57,960 如果说你是在页式存储管理里头没有虚拟的话 125 00:05:58,000 --> 00:05:59,880 那么它就是访存的时间 126 00:05:59,920 --> 00:06:02,440 因为我所有的内容都在内存里头 127 00:06:02,480 --> 00:06:05,840 我直接读就可以 读内存的时间是固定的 128 00:06:05,880 --> 00:06:08,600 大家是一致的 但是有了虚拟之后 129 00:06:08,640 --> 00:06:10,440 那我们就只能有一部分是 130 00:06:10,480 --> 00:06:12,320 直接从内存当中访问的 131 00:06:12,360 --> 00:06:15,520 而另外一部分呢我是从硬盘上读的 132 00:06:15,560 --> 00:06:20,800 那从硬盘上读呢 要涉及到缺页异常的处理时间 133 00:06:20,840 --> 00:06:23,600 那这时候根据你缺页率 134 00:06:23,640 --> 00:06:28,240 缺页率E减P那是你的内存访问 135 00:06:28,280 --> 00:06:31,760 而概率P呢你是从硬盘上访问 136 00:06:31,800 --> 00:06:34,440 这俩加到一起平均下来就是 137 00:06:34,480 --> 00:06:38,080 你的存储访问的有效访问时间 138 00:06:38,120 --> 00:06:40,080 那下面我们用一个例子来说 139 00:06:40,120 --> 00:06:45,200 假定我访问内存的时间是10个纳秒 140 00:06:45,240 --> 00:06:49,200 而一次访问磁盘的时间是5个毫秒 141 00:06:49,240 --> 00:06:52,160 而在这里头缺页率设置为P 142 00:06:52,200 --> 00:06:56,680 那缺页里头有一些需要做过修改的 143 00:06:56,720 --> 00:06:59,360 页修改概率为Q 那这时候 144 00:06:59,400 --> 00:07:04,560 我的有效存储访问时间是多少呢 145 00:07:04,600 --> 00:07:13,080 在这儿这个表达 10纳秒乘以1减缺页率P 146 00:07:13,120 --> 00:07:16,920 那这时候存储在内存里情况的访问 147 00:07:16,960 --> 00:07:20,160 然后剩下的是会在磁盘上的访问 148 00:07:20,200 --> 00:07:22,880 我们在这儿缺页异常处理时间 149 00:07:22,920 --> 00:07:25,160 主要是你磁盘访问时间 150 00:07:25,200 --> 00:07:27,920 而代码执行时间我们在这儿忽略不计了 151 00:07:27,960 --> 00:07:31,840 好 那在这里头呢 基本上是说5个毫秒 152 00:07:31,880 --> 00:07:35,200 是10个纳秒的50万倍 153 00:07:35,240 --> 00:07:37,120 50万倍乘在这里头来 154 00:07:37,160 --> 00:07:41,240 然后这边呢缺页率是概率P 155 00:07:41,280 --> 00:07:43,480 然后在这里头呢它是乘1 156 00:07:43,520 --> 00:07:45,440 还要加上一项什么呢 157 00:07:45,480 --> 00:07:49,760 对于修改过的我是两个5毫秒 158 00:07:49,800 --> 00:07:52,560 那这时候再加上一个Q 159 00:07:52,600 --> 00:07:57,640 这个P乘Q是你这个缺页情况下再加上页修改 160 00:07:57,680 --> 00:08:01,080 这俩搁在一起那最后是我们的有效时间 161 00:08:01,120 --> 00:08:03,960 如果你想让这个最后这个 162 00:08:04,000 --> 00:08:07,960 有效存储访问时间和这个10纳秒不相上下 163 00:08:08,000 --> 00:08:09,920 或者稍微大一点的话 164 00:08:09,960 --> 00:08:13,560 那么这个时候你的缺页率这个P必须足够小 165 00:08:13,600 --> 00:08:17,960 以至于可以把这个50万倍基本上给抵消了 166 00:08:18,000 --> 00:08:20,760 那这样以来的话我这个地方有效时间 167 00:08:20,800 --> 00:08:25,440 才会可以和原来的存储访问相一致 168 00:08:25,480 --> 00:08:30,240 那这是我们说虚拟页式存储管理的性能 169 00:08:30,280 --> 00:08:31,440 那到这个地方呢 170 00:08:31,480 --> 00:08:37,080 我们关于虚拟存储管理的概念就讲完了 171 00:08:37,120 --> 00:08:39,120 那我们在这里还有一个问题没有涉及 172 00:08:39,160 --> 00:08:42,440 就是我们在这里说我缺页中断 173 00:08:42,480 --> 00:08:45,720 中断完了之后我要用页面置换算法 174 00:08:45,760 --> 00:08:51,560 来选择一个页面来 用来存我先要加进来东西 175 00:08:51,600 --> 00:08:53,120 那这个地方如何选择呢 176 00:08:53,160 --> 00:08:57,480 这是我们下一次要讨论页面置换算法的内容 177 00:08:57,520 --> 00:09:01,000 好 那今天的课就上到这里 下课 178 00:09:01,040 --> 00:09:06,800 179 00:09:06,840 --> 00:09:07,520 180 00:09:07,560 --> 00:09:08,320 181 00:09:08,360 --> 00:09:08,400