0 00:00:00,000 --> 00:00:06,520 1 00:00:06,720 --> 00:00:12,320 好 接下来我们介绍中断异常和系统调用 2 00:00:12,360 --> 00:00:16,640 那在这里呢 我们会说中断异常和系统调用 3 00:00:16,680 --> 00:00:20,280 它到底是用来干什么 解决什么问题 4 00:00:20,320 --> 00:00:22,640 然后这几个的应用场景 5 00:00:22,680 --> 00:00:25,760 或者说他们之间有些什么样的区别和联系 6 00:00:25,800 --> 00:00:29,480 它在用处的时候 它们之间会有一些差异 7 00:00:29,520 --> 00:00:32,440 但是也有很多会共同的东西 8 00:00:32,480 --> 00:00:35,200 再一个就是说我们需要来说明 9 00:00:35,240 --> 00:00:42,120 中断异常和系统调用它的实现机制 10 00:00:42,160 --> 00:00:46,200 首先我们说在上前边的内容里头已经说过 11 00:00:46,240 --> 00:00:49,280 操作系统 计算机系统启来了之后 12 00:00:49,320 --> 00:00:52,040 它会加载操作系统的内核 13 00:00:52,080 --> 00:00:55,040 然后就把控制权转给操作系统内核了 14 00:00:55,080 --> 00:00:58,640 在这前面这一段呢 是可以信任的 15 00:00:58,680 --> 00:01:00,880 但是在操作系统内核之上呢 16 00:01:00,920 --> 00:01:02,840 实际上我们还有很多的应用程序 17 00:01:02,880 --> 00:01:04,480 这些应用程序我们没有办法 18 00:01:04,520 --> 00:01:06,800 对它做到完全的信任 19 00:01:06,840 --> 00:01:11,400 而这应用程序要使用操作系统内核提供的服务 20 00:01:11,440 --> 00:01:12,480 那这时候怎么办呢 21 00:01:12,520 --> 00:01:15,680 实际上我们就需要解决一个操作系统内核 22 00:01:15,720 --> 00:01:18,560 和外界打交道的问题 23 00:01:18,600 --> 00:01:21,720 那我们说操作系统内核是可以信赖的 24 00:01:21,760 --> 00:01:26,160 我可以在里做对计算机系统里的任何内容的控制 25 00:01:26,200 --> 00:01:29,640 可以执行它的特权指令 这种信任呢 26 00:01:29,680 --> 00:01:32,160 并不是它跟外界完全的隔离 27 00:01:32,200 --> 00:01:36,320 它还需要为上边的应用程序提供服务 28 00:01:36,360 --> 00:01:40,400 也就是说我可以信任的内核 29 00:01:40,440 --> 00:01:44,520 它必须对外界提供某种访问的接口 30 00:01:44,560 --> 00:01:48,800 或者打交道的通道 然后再一个呢 31 00:01:48,840 --> 00:01:53,800 我们除了会是跟应用程序打交道之外 32 00:01:53,840 --> 00:01:56,160 我们在程序或者计算机系统 33 00:01:56,200 --> 00:01:58,720 在运行过程当中会有各种各样的问题 34 00:01:58,760 --> 00:02:00,760 比如说我在外设 35 00:02:00,800 --> 00:02:03,280 你在跟他做交互的时候你敲键盘 36 00:02:03,320 --> 00:02:05,640 我并不能确认 你会在什么时间 37 00:02:05,680 --> 00:02:08,280 准确的一个什么时间点去敲键盘 38 00:02:08,320 --> 00:02:12,080 你敲了键盘之后 可能我的系统正在干别的事 39 00:02:12,120 --> 00:02:14,560 这时候我没办法给你做出响应 40 00:02:14,600 --> 00:02:16,000 那这样的话就会让你感觉 41 00:02:16,040 --> 00:02:18,120 这个计算机系统很不好用 42 00:02:18,160 --> 00:02:22,400 所以为了能够让计算机系统 43 00:02:22,440 --> 00:02:26,160 能够对外界做出适当的反映 44 00:02:26,200 --> 00:02:27,840 我们需要提出中断机制 45 00:02:27,880 --> 00:02:30,840 也就是说当外设与系统有交互的时候 46 00:02:30,880 --> 00:02:33,280 我需要怎么来处理 47 00:02:33,320 --> 00:02:34,160 还有一种情况呢 48 00:02:34,200 --> 00:02:36,760 是说我的应用程序在执行过程当中 49 00:02:36,800 --> 00:02:38,760 比如说我做除法 除了一个零 50 00:02:38,800 --> 00:02:40,360 那这时候是要出问题呢 51 00:02:40,400 --> 00:02:41,640 而是否会除零呢 52 00:02:41,680 --> 00:02:43,920 我只有执行到那一步的时候我才知道 53 00:02:43,960 --> 00:02:45,680 好 等到这个时候你再知道的话 54 00:02:45,720 --> 00:02:48,000 那我已经没办法往下做了 55 00:02:48,040 --> 00:02:50,320 所以总会有一些意外情况 56 00:02:50,360 --> 00:02:53,520 我在事先写程序的时候我是没办法预料到的 57 00:02:53,560 --> 00:02:55,240 对于这种意外的情况 58 00:02:55,280 --> 00:02:57,640 我们怎么来处理 所以在我们这里呢 59 00:02:57,680 --> 00:03:02,120 通常的做法是说应用程序提供你所需要的功能 60 00:03:02,160 --> 00:03:05,400 那里头的异常呢 这种意外的情况呢 61 00:03:05,440 --> 00:03:07,800 把它控制权转给操作系统 62 00:03:07,840 --> 00:03:09,600 由操作系统来处理它 63 00:03:09,640 --> 00:03:12,880 这是我们这里说到的应用程序执行当中意外 64 00:03:12,920 --> 00:03:16,360 有异常来做处理 那还有一种情况呢 65 00:03:16,400 --> 00:03:20,840 是说我们要解决用户程序如何来解决系统的服务 66 00:03:20,880 --> 00:03:24,640 就好象说我们提供给银行对外提供服务 67 00:03:24,680 --> 00:03:28,200 银行为了保证安全 所以它有很多的防护 68 00:03:28,240 --> 00:03:32,280 这个防护又和对外提供服务这是有矛盾的 69 00:03:32,320 --> 00:03:34,760 为了方便用户来使用银行的服务 70 00:03:34,800 --> 00:03:38,200 你必须提供灵活的访问接口 71 00:03:38,240 --> 00:03:41,360 但是这种灵活的接口 又不能影响到银行的安全 72 00:03:41,400 --> 00:03:43,400 操作系统内核也是一样的 73 00:03:43,440 --> 00:03:46,760 我们需要来通过系统调用来提供一个接口 74 00:03:46,800 --> 00:03:50,240 让应用程序既方便的使用内核提供的服务 75 00:03:50,280 --> 00:03:55,000 又不至于用户的行为对我内核的安全产生影响 76 00:03:55,040 --> 00:03:58,200 那也就是说使用服务呢 我们有很多种方式 77 00:03:58,240 --> 00:04:00,440 那在这里头呢 用内核提供服务 78 00:04:00,480 --> 00:04:02,960 和我们通常写程序的时候用函数库 79 00:04:03,000 --> 00:04:06,360 来提供服务有啥区别 那这是我们在这里呢 80 00:04:06,400 --> 00:04:10,360 你在选择用系统调用 还是用函数库的时候 81 00:04:10,400 --> 00:04:12,960 需要做出的判断 82 00:04:13,000 --> 00:04:16,000 好 有了刚才这些问题我们来看 83 00:04:16,040 --> 00:04:18,960 用下边这个图来看一下 84 00:04:19,000 --> 00:04:21,320 内核和外界之间打交道的地方 85 00:04:21,360 --> 00:04:24,040 这是我们内核 然后我们在里呢 86 00:04:24,080 --> 00:04:27,920 提供了相应的一些内核服务 这些内核服务 87 00:04:27,960 --> 00:04:32,640 首先会是说跟外界的硬件打交道 88 00:04:32,680 --> 00:04:36,640 比如说我敲了键盘 那我在敲下一个键的时候 89 00:04:36,680 --> 00:04:38,680 可能里头会有一个缓冲区 90 00:04:38,720 --> 00:04:41,200 缓冲区的大小是有限制的 91 00:04:41,240 --> 00:04:43,560 那存多了 前边的内容就会丢 92 00:04:43,600 --> 00:04:45,920 好 那我在这里呢 有数据之后 93 00:04:45,960 --> 00:04:48,200 我就必须告诉操作系统 94 00:04:48,240 --> 00:04:50,440 那你在这里面及时把我的数据读走 95 00:04:50,480 --> 00:04:51,080 否则的话 96 00:04:51,120 --> 00:04:53,880 后边来的数据就会丢了 那这时候呢 97 00:04:53,920 --> 00:04:56,840 有一条通道 那这就是我们这里的中断 98 00:04:56,880 --> 00:05:00,480 好中断 通知内核 内核通过驱动 99 00:05:00,520 --> 00:05:03,760 来与你的设备进行数据的交互 100 00:05:03,800 --> 00:05:06,080 比如说键盘我是读进去 磁盘的话 101 00:05:06,120 --> 00:05:11,040 即是会有读有写 然后还有一种情况是说 102 00:05:11,080 --> 00:05:13,440 应用程序在执行的过程当中 103 00:05:13,480 --> 00:05:17,240 好 正常执行 那跟内核没关系 104 00:05:17,280 --> 00:05:19,480 好 执行到某一个位置的时候 105 00:05:19,520 --> 00:05:22,840 比如说某条指令做除法 除了个零 106 00:05:22,880 --> 00:05:25,240 或者说一条存储访问指令 107 00:05:25,280 --> 00:05:27,200 访问到某一个存储单元 108 00:05:27,240 --> 00:05:29,400 但这个存储单元是不允许你访问的 109 00:05:29,440 --> 00:05:32,720 就好比说储户你想说银行里有你的钱 110 00:05:32,760 --> 00:05:34,640 你就想直接去开银行的保险柜 111 00:05:34,680 --> 00:05:37,040 把你的钱取出来 那这是不行的 112 00:05:37,080 --> 00:05:38,200 对于这种情况呢 113 00:05:38,240 --> 00:05:41,200 我们在这里跟操作系统是类似的 114 00:05:41,240 --> 00:05:44,320 它会提供一个异常机制 115 00:05:44,360 --> 00:05:45,960 那我们把这些情况都认为 116 00:05:46,000 --> 00:05:48,400 是你代码执行过程当中的出错 117 00:05:48,440 --> 00:05:51,680 有些错误呢 实际上是我们事先有预计的 118 00:05:51,720 --> 00:05:54,720 好 那这时候呢 把空闲交到内核 119 00:05:54,760 --> 00:05:56,720 内核可能做出的处理呢 120 00:05:56,760 --> 00:06:00,000 要么说我把你遇到的问题解决掉 121 00:06:00,040 --> 00:06:03,160 比如说你访问到的某一个存储单元 122 00:06:03,200 --> 00:06:05,000 原来的存储单元不存在 123 00:06:05,040 --> 00:06:08,800 好 那我把原来的存储单元的内容放到内存里头 124 00:06:08,840 --> 00:06:10,680 OK 对于虚拟存储来讲 125 00:06:10,720 --> 00:06:12,080 这时候你就可以执行了 126 00:06:12,120 --> 00:06:16,200 而另外一些问题 比如说像是除零之类的 127 00:06:16,240 --> 00:06:19,200 那你这时候除零 我就没有办法继续下去 128 00:06:19,240 --> 00:06:20,720 这时候我就会把应用程序 129 00:06:20,760 --> 00:06:24,160 所占这些资源还给操作系统 130 00:06:24,200 --> 00:06:27,720 那这是我们异常 那最主要的一类呢 131 00:06:27,760 --> 00:06:29,200 是正常情况下的使用 132 00:06:29,240 --> 00:06:31,600 应用程序会使用到函数库 133 00:06:31,640 --> 00:06:33,160 那这时候跟内核不打交道 134 00:06:33,200 --> 00:06:36,640 但是内核 应用程序或者函数库 135 00:06:36,680 --> 00:06:39,400 会间接的通过系统调用接口 136 00:06:39,440 --> 00:06:41,720 使用到操作系统内核的服务 137 00:06:41,760 --> 00:06:45,720 比如说我要读写文件 138 00:06:45,760 --> 00:06:49,080 那我应用程序不能直接访问磁盘设备 139 00:06:49,120 --> 00:06:51,440 它怎么办呢 发出操作系统 140 00:06:51,480 --> 00:06:56,640 提供了一个磁盘读写的一个系统调用接口 141 00:06:56,680 --> 00:07:00,440 好 那应用程序通过调用这个 142 00:07:00,480 --> 00:07:03,080 读写接口所提供的这个函数 143 00:07:03,120 --> 00:07:05,640 好 那这时候进到内核里头来 144 00:07:05,680 --> 00:07:07,480 内核把相应的数据读出来 145 00:07:07,520 --> 00:07:11,520 还给应用程序 那这个流程就结束了 146 00:07:11,560 --> 00:07:12,720 所以从这我们可以看到 147 00:07:12,760 --> 00:07:16,840 操作系统内核和外界打交道基本上就是中断 148 00:07:16,880 --> 00:07:20,920 异常和系统调用这三个接口 149 00:07:20,960 --> 00:07:25,200 这是我们在这里说到这三条 150 00:07:25,240 --> 00:07:26,840 从这三条我们就可以看到 151 00:07:26,880 --> 00:07:29,320 中断 异常和系统调用他们之间 152 00:07:29,360 --> 00:07:31,320 到底有什么样的定义 153 00:07:31,360 --> 00:07:33,640 系统调用是应用程序 154 00:07:33,680 --> 00:07:39,200 主动向操作系统发出的服务请求 155 00:07:39,240 --> 00:07:44,240 而异常呢 是非法指令或者其他原因 156 00:07:44,280 --> 00:07:49,360 导致的指令执行失败之后的处理请求 157 00:07:49,400 --> 00:07:53,000 那这种处理请求呢 可能会是说我终止程序 158 00:07:53,040 --> 00:07:56,120 也可能会是说解决你遇到的问题 159 00:07:56,160 --> 00:07:59,680 然后重新执行这条指令 而中断呢 160 00:07:59,720 --> 00:08:03,880 是硬件设备对操作系统提出的处理请求 161 00:08:03,920 --> 00:08:05,640 比如说我缓冲区里有数据 162 00:08:05,680 --> 00:08:07,080 需要内核把它读走 163 00:08:07,120 --> 00:08:09,840 或者说我缓冲区里的数据已经全部用完 164 00:08:09,880 --> 00:08:12,320 需要内核补充新的数据 165 00:08:12,360 --> 00:08:16,720 那这里我们说到的中断异常和系统调用 166 00:08:16,760 --> 00:08:20,280 那这三者之间的区别到底怎么来描述呢 167 00:08:20,320 --> 00:08:22,440 我们可以从这样几条来区别 168 00:08:22,480 --> 00:08:25,480 第一个是它的源头 那在这呢 169 00:08:25,520 --> 00:08:30,560 我们标出了系统调用的触发条件 170 00:08:30,600 --> 00:08:35,160 中断的起头和异常的起头 171 00:08:35,200 --> 00:08:39,240 这三个分别对应着我们这里的来源不同 172 00:08:39,280 --> 00:08:44,400 外设 应用程序 实际上这个异常 173 00:08:44,440 --> 00:08:47,360 在这个图里描述是适宜性的 174 00:08:47,400 --> 00:08:49,120 我在执行内核代码的时候 175 00:08:49,160 --> 00:08:51,600 也可能由于代码的执行出现问题 176 00:08:51,640 --> 00:08:56,880 这时候呢 也可能是内部出现的 177 00:08:56,920 --> 00:09:00,560 然后第二个呢 是他们的响应方式不一样 178 00:09:00,600 --> 00:09:06,440 那这三个箭头分别对应着系统 调用 179 00:09:06,480 --> 00:09:12,480 中断和异常的响应方式 那系统调用呢 180 00:09:12,520 --> 00:09:15,200 通常情况下我们会是同步的或者异步的 181 00:09:15,240 --> 00:09:18,560 也就是说应用程序发出系统调用请求 182 00:09:18,600 --> 00:09:19,680 然后它就在那等着了 183 00:09:19,720 --> 00:09:23,640 一直到你算完内核服务完成之后给它结果 184 00:09:23,680 --> 00:09:25,640 那也可能是异步的 185 00:09:25,680 --> 00:09:28,400 说我们在这里系统调用发出了之后 186 00:09:28,440 --> 00:09:29,600 你内核在处理时候 187 00:09:29,640 --> 00:09:30,520 处理的过程当中 188 00:09:30,560 --> 00:09:32,520 我就切换过去干别的事情过去了 189 00:09:32,560 --> 00:09:34,600 然后等到其他条件准备之后 190 00:09:34,640 --> 00:09:39,480 你这才会回来 而中断的它是异步的 191 00:09:39,520 --> 00:09:41,200 也就是说你上边应用程序 192 00:09:41,240 --> 00:09:43,480 该怎么做处理怎么做处理 193 00:09:43,520 --> 00:09:47,600 我不会感知到中断的存在 194 00:09:47,640 --> 00:09:50,360 那中断只是在应用程序暂停执行 195 00:09:50,400 --> 00:09:53,720 处理完中断所需要的服务之后 196 00:09:53,760 --> 00:09:55,480 继续恢复你应用程序的执行 197 00:09:55,520 --> 00:09:57,400 就跟没有这件事情一样 198 00:09:57,440 --> 00:10:01,600 而异常是跟你的这个当前指令有关的 199 00:10:01,640 --> 00:10:04,200 这个是同步的 也就是说必须处理完 200 00:10:04,240 --> 00:10:08,920 当前这条异常所产生的指令所导致的问题 201 00:10:08,960 --> 00:10:13,000 我才可以继续下去 那当然他们之间的处理呢 202 00:10:13,040 --> 00:10:15,120 会都在内核里头来做 203 00:10:15,160 --> 00:10:17,400 但他们的处理也会有一些区别 204 00:10:17,440 --> 00:10:19,400 中断会持续的进行 205 00:10:19,440 --> 00:10:24,400 而系统调用它会是用户提出之后会处理 206 00:10:24,440 --> 00:10:27,240 等待然后再继续 而异常呢 207 00:10:27,280 --> 00:10:33,360 是会处理当前所出现的问题 208 00:10:33,400 --> 00:10:36,200 那具体说起来 中断的处理 209 00:10:36,240 --> 00:10:40,960 那这个中断实际上我们把它理解为 210 00:10:41,000 --> 00:10:44,800 系统调用异常和中断这三种情况的总称 211 00:10:44,840 --> 00:10:46,520 对于硬件上的处理呢 212 00:10:46,560 --> 00:10:49,360 这主要是在硬件中那个地方 213 00:10:49,400 --> 00:10:51,680 在CPU做初始化的时候 214 00:10:51,720 --> 00:10:54,800 它其中就有一项工作 要对中断使能 215 00:10:54,840 --> 00:10:59,800 也就是说在许可外界打扰CPU的执行之前 216 00:10:59,840 --> 00:11:03,680 CPU是不会对外界的任何中断请求发出响应的 217 00:11:03,720 --> 00:11:07,960 那只有我CPU把相应的准备工作做完 218 00:11:08,000 --> 00:11:10,280 外界来一个请求之后 我知道怎么处理了 219 00:11:10,320 --> 00:11:13,080 我才会允许这种处理 220 00:11:13,120 --> 00:11:14,480 如果我不知道怎么处理的话 221 00:11:14,520 --> 00:11:16,680 你给我一个请求 我也不知道怎么办 222 00:11:16,720 --> 00:11:18,360 所以在这 在初始化的时候 223 00:11:18,400 --> 00:11:20,560 它有一个中断使能 使能之后 224 00:11:20,600 --> 00:11:23,960 我才能够进行中断的处理 225 00:11:24,000 --> 00:11:27,200 第二个是说这个事件产生了 226 00:11:27,240 --> 00:11:30,600 产生了之后通常是一个电平的上升沿 227 00:11:30,640 --> 00:11:32,520 或者说是一个高电平 228 00:11:32,560 --> 00:11:35,200 那CPU会记录下这件事情 229 00:11:35,240 --> 00:11:36,640 也就是说我有一个中断标志 230 00:11:36,680 --> 00:11:40,360 表示出现了一个中断 231 00:11:40,400 --> 00:11:43,600 然后这时候我需要知道中断 232 00:11:43,640 --> 00:11:45,160 到底是由什么设备产生的 233 00:11:45,200 --> 00:11:46,720 需要知道中断源的编号 234 00:11:46,760 --> 00:11:49,320 这一部分工作是由硬件来做的 235 00:11:49,360 --> 00:11:51,640 好 硬件做完这一部分工作之后 236 00:11:51,680 --> 00:11:55,880 剩下的事情就是由内核的软件来做 237 00:11:55,920 --> 00:11:57,760 那在这里头呢 238 00:11:57,800 --> 00:12:01,920 也就是说这几个进来都到了这个中断向量表 239 00:12:01,960 --> 00:12:04,160 中断向量表如果是中断 240 00:12:04,200 --> 00:12:08,600 那它直接绕到这边的中断服务例程 241 00:12:08,640 --> 00:12:10,800 驱动程序里来做出响应 242 00:12:10,840 --> 00:12:16,800 如果是异常 它直接转到异常服务例程来做处理 243 00:12:16,840 --> 00:12:20,520 如果说是系统调用 由于系统调用的量很大 244 00:12:20,560 --> 00:12:23,120 那我们在这儿 系统调用之后 245 00:12:23,160 --> 00:12:27,120 系统调用它之后总共占用一个中断编号 246 00:12:27,160 --> 00:12:30,480 然后它自己的不同的系统调用的功能呢 247 00:12:30,520 --> 00:12:33,360 是用系统调用表来表示的 248 00:12:33,400 --> 00:12:35,920 好 在这呢 根据你系统调用表里的 249 00:12:35,960 --> 00:12:37,160 功能的选择不同 250 00:12:37,200 --> 00:12:40,960 我去选择不同的系统调用实现 251 00:12:41,000 --> 00:12:42,880 那么在这个过程里头呢 252 00:12:42,920 --> 00:12:47,120 我为了不影响程序的正常执行 253 00:12:47,160 --> 00:12:50,400 我前边有一个保护现场和恢复现场 254 00:12:50,440 --> 00:12:53,360 而在这里头呢 要做系统调用的交互 255 00:12:53,400 --> 00:12:56,880 我还需要知道系统调用产生之前 256 00:12:56,920 --> 00:13:00,400 我准备的上下文的信息 比如说你到底让我干啥 257 00:13:00,440 --> 00:13:05,360 那这一部分工作呢 是会和你的编译有关系 258 00:13:05,400 --> 00:13:07,880 然后中间这一部分到底如何实现 259 00:13:07,920 --> 00:13:10,640 那这个是由操作系统来做的 260 00:13:10,680 --> 00:13:12,080 然后如果是中断的话 261 00:13:12,120 --> 00:13:13,960 那么你在执行的过程当中 262 00:13:14,000 --> 00:13:15,840 需要清除这个中断标志 263 00:13:15,880 --> 00:13:23,360 这个也是由你的中断服务例程来完成的 264 00:13:23,400 --> 00:13:28,320 好 我们说中断可以满足应用程序 265 00:13:28,360 --> 00:13:32,160 外部设备 或者程序执行异常的服务请求 266 00:13:32,200 --> 00:13:33,880 那这时候可能会出现一种情况 267 00:13:33,920 --> 00:13:35,920 我正在处理一个请求的时候 268 00:13:35,960 --> 00:13:38,200 有来了一个请求这时候我怎么办 269 00:13:38,240 --> 00:13:41,280 那我们说在操作系统的里头呢 270 00:13:41,320 --> 00:13:44,560 它是硬件的中断 它是允许被打断的 271 00:13:44,600 --> 00:13:46,800 也就是说我正在处理一个中断的时候 272 00:13:46,840 --> 00:13:49,960 可以允许你再出现其他的中断 273 00:13:50,000 --> 00:13:52,520 如果两个中断源不同 那这时候呢 274 00:13:52,560 --> 00:13:54,800 我可以通过优先级的高低 275 00:13:54,840 --> 00:13:56,680 让一个往后推一段 276 00:13:56,720 --> 00:13:58,760 或者说让一个暂停下来 277 00:13:58,800 --> 00:14:00,480 那使得我可以同时在做 278 00:14:00,520 --> 00:14:04,760 交替在做处理 然后在中断服务例程里头 279 00:14:04,800 --> 00:14:08,160 并不是说我任何一个时刻都可以做任何一个处理 280 00:14:08,200 --> 00:14:09,560 它会在一定的时间里呢 281 00:14:09,600 --> 00:14:13,360 禁止中断请求 比如说我电源有问题 282 00:14:13,400 --> 00:14:16,240 那可能其他的问题就变得不重要了 283 00:14:16,280 --> 00:14:19,840 这时候我在做电源的处理的时候 284 00:14:19,880 --> 00:14:21,640 我就会禁止掉其他中断 285 00:14:21,680 --> 00:14:25,920 然后中断服务请求会一直保持到CPU做出响应 286 00:14:25,960 --> 00:14:29,480 然后对于异常呢 我也可以被打断 287 00:14:29,520 --> 00:14:32,560 你比如说我在程序执行当中出现了异常 288 00:14:32,600 --> 00:14:35,000 这时候正在做异常的处理 289 00:14:35,040 --> 00:14:37,240 比如说我在这里头虚拟存储里头 290 00:14:37,280 --> 00:14:39,560 它访问到的存储单元的数据不存在 291 00:14:39,600 --> 00:14:41,880 我正在从硬盘上倒数据进来 292 00:14:41,920 --> 00:14:45,840 倒的过程当中 它会用到磁盘I/O 293 00:14:45,880 --> 00:14:48,680 这时候也会再有磁盘设备的中断 294 00:14:48,720 --> 00:14:51,240 这时候是允许它可以做嵌套的 295 00:14:51,280 --> 00:14:54,400 然后对于异常服务的嵌套呢 296 00:14:54,440 --> 00:14:57,600 这是我们说到的 异常服务和缺页 297 00:14:57,640 --> 00:15:01,240 这两个在异常服务里头还会再出现异常 298 00:15:01,280 --> 00:15:03,240 也就是说我执行中断 299 00:15:03,280 --> 00:15:05,560 执行异常处理例程里头 300 00:15:05,600 --> 00:15:07,800 有一段存储访问它是缺页的 301 00:15:07,840 --> 00:15:12,000 那这时候两个异常也是可以嵌套到一起 302 00:15:12,040 --> 00:15:12,080 303 00:15:12,120 --> 00:15:12,160