0 00:00:00,000 --> 00:00:16,160 1 00:00:16,280 --> 00:00:19,280 各位同学我们这次课主要讲的是 2 00:00:19,400 --> 00:00:21,480 操作系统的第二个实验 3 00:00:21,520 --> 00:00:25,760 关于物理内存的管理 4 00:00:25,800 --> 00:00:27,800 那我们原理课里面 5 00:00:27,840 --> 00:00:30,800 其实对这个内存管理做了很深入的讲解 6 00:00:30,840 --> 00:00:36,120 主要是说物理内存它的相关的一些细节 7 00:00:36,160 --> 00:00:38,240 比如说怎么去建立映射关系 8 00:00:38,280 --> 00:00:41,040 物理内存相应的一些它的作用等等 9 00:00:41,080 --> 00:00:42,480 给大家做了一个讲解 10 00:00:42,520 --> 00:00:44,840 那我们这里面是想结合实验让大家对 11 00:00:44,880 --> 00:00:46,960 这个物理内存有一个更深入的理解 12 00:00:47,000 --> 00:00:48,920 看看操作系统怎么来 13 00:00:48,960 --> 00:00:50,800 对物理内存进行有效的管理 14 00:00:50,840 --> 00:00:53,840 这里面有两个比较困难的地方 15 00:00:53,880 --> 00:00:56,120 第一个是关于特权级 16 00:00:56,160 --> 00:00:59,240 因为我们说操作系统加上我们的CPU 17 00:00:59,280 --> 00:01:02,080 给我们不同的应用程序提供一个隔离的空间 18 00:01:02,120 --> 00:01:05,320 这点需要有一个保护机制 那这是一个 19 00:01:05,360 --> 00:01:08,880 第二个我们的应用程序不能够随随便便的去 20 00:01:08,920 --> 00:01:10,520 访问我们的操作系统的空间 21 00:01:10,560 --> 00:01:13,160 这一点也是通过保护机制来实现的 22 00:01:13,200 --> 00:01:15,080 这里面有一个特权级这么一个概念 23 00:01:15,120 --> 00:01:18,480 我们希望通过lab2让大家能够知道 24 00:01:18,520 --> 00:01:21,480 操作系统怎么利用CPU的硬件机制来建立 25 00:01:21,520 --> 00:01:22,920 所谓的保护机制 26 00:01:22,960 --> 00:01:25,560 这是第一个特权级这一块给大家做一个讲解 27 00:01:25,600 --> 00:01:28,200 第二部分是关于内存管理单元 28 00:01:28,240 --> 00:01:29,560 X86的内存管理单元 29 00:01:29,600 --> 00:01:31,880 那我们这里面讲的更多的是基于X86的 30 00:01:31,920 --> 00:01:33,800 MMU 这个内存管理单元 31 00:01:33,840 --> 00:01:36,080 来看我们操作系统怎么利用 32 00:01:36,120 --> 00:01:40,880 这个MMU的功能来实现内存的映射 33 00:01:40,920 --> 00:01:43,080 这实际上就是说可以把 34 00:01:43,120 --> 00:01:45,480 我们的虚拟的连续地址空间 35 00:01:45,520 --> 00:01:49,960 映射到分散的离散的物理空间里面去 36 00:01:50,000 --> 00:01:52,160 这两者之间是有差别的 37 00:01:52,200 --> 00:01:55,920 那么这个差别是通过我们的X86内存管理单元 38 00:01:55,960 --> 00:01:58,480 在操作系统的管理之下来实现的 39 00:01:58,520 --> 00:02:01,120 那这两点需要大家能够理解 40 00:02:01,160 --> 00:02:04,160 所以我们这一讲主要是给大家讲一下 41 00:02:04,200 --> 00:02:05,720 硬件到底做了什么事情 42 00:02:05,760 --> 00:02:06,680 我们操作系统怎么利用 43 00:02:06,720 --> 00:02:09,880 这个相应的一些机制来完成这些功能 44 00:02:09,920 --> 00:02:13,240 从而可以实现操作系统物理内存的管理 45 00:02:13,280 --> 00:02:15,360 46 00:02:15,400 --> 00:02:18,240 首先我们看一下X86的特权级 47 00:02:18,280 --> 00:02:20,920 那首先我们要知道就是这个硬件 48 00:02:20,960 --> 00:02:23,200 我们CPU到底提供了几种特权级 49 00:02:23,240 --> 00:02:25,360 然后我们的程序在跑的时候 50 00:02:25,400 --> 00:02:28,200 我们的CPU到底当前处于哪样特权级 51 00:02:28,240 --> 00:02:29,840 就是说你应用程序到底处于什么特权级 52 00:02:29,880 --> 00:02:33,760 你怎么知道的 你的应用程序是在内核态跑的 53 00:02:33,800 --> 00:02:35,120 还是在用户态跑的 54 00:02:35,160 --> 00:02:39,920 第三个我们说我们的应用程序跑在用户态 55 00:02:39,960 --> 00:02:42,440 但可能过了一会儿又跑到内核态 56 00:02:42,480 --> 00:02:44,760 我们操作系统在运行 那么这个来回的切换 57 00:02:44,800 --> 00:02:46,640 涉及到一个所谓的特权级的切换 58 00:02:46,680 --> 00:02:49,320 那这个切换过程怎么实现的 59 00:02:49,360 --> 00:02:51,480 这是我们说这一节里面要讲的内容 60 00:02:51,520 --> 00:02:53,240 就是X86特权级的一个问题 61 00:02:53,280 --> 00:02:57,880 好 那我们接下来看一下 第一个是了解特权级 62 00:02:57,920 --> 00:02:59,440 我们看一下X86特权级 63 00:02:59,480 --> 00:03:03,720 X86特权级你可以看到它有0 1 2 3 64 00:03:03,760 --> 00:03:08,440 四个特权级 其中内核是处于0特权级 65 00:03:08,480 --> 00:03:11,400 因为就是我们特权级最高的地方就在Level 0 66 00:03:11,440 --> 00:03:15,480 那么我们的应用程序一般是放在Level 3 67 00:03:15,520 --> 00:03:18,240 就是Applications 这个应用程序放在Level 3 68 00:03:18,280 --> 00:03:20,240 那么也意味着应用程序 69 00:03:20,280 --> 00:03:23,840 无法去破坏内核里面的代码或者数据 70 00:03:23,880 --> 00:03:26,720 但是它可以得到内核态代码的服务 71 00:03:26,760 --> 00:03:27,960 它可以得到它的服务 72 00:03:28,000 --> 00:03:29,880 同时看到还有Level 1 Level 2 73 00:03:29,920 --> 00:03:33,680 那么当时intel设计CPU的时候考虑比较灵活 74 00:03:33,720 --> 00:03:35,000 说我们还有其它一些应用 75 00:03:35,040 --> 00:03:39,160 也许需要更多的层级来做区分 76 00:03:39,200 --> 00:03:40,880 但其实在我们现在的 77 00:03:40,920 --> 00:03:43,720 操作系统设计里面一般来说 78 00:03:43,760 --> 00:03:44,400 只需要两级 79 00:03:44,440 --> 00:03:47,640 就是一个操作系统Kernel有一个级别 80 00:03:47,680 --> 00:03:49,440 一个是我们应用程序有一个级别 81 00:03:49,480 --> 00:03:51,360 就够了 基本上就够了 82 00:03:51,400 --> 00:03:54,560 所以说对于我们lab2这个实验来说 83 00:03:54,600 --> 00:03:58,080 它只需用Level 0和Level 3就够了 84 00:03:58,120 --> 00:04:01,720 一个是用来给我们操作系统ucore来跑的 85 00:04:01,760 --> 00:04:03,960 来访问数据和运行 86 00:04:04,000 --> 00:04:05,480 执行一些特权指令等等 87 00:04:05,520 --> 00:04:07,240 那么另外一个是我们应用程序 88 00:04:07,280 --> 00:04:11,480 它跑到Level 3 这是我们说X86特权级里面 89 00:04:11,520 --> 00:04:13,120 我们的操作系统怎么去利用的 90 00:04:13,160 --> 00:04:14,360 那对于我们常见的操作系统 91 00:04:14,400 --> 00:04:15,960 比如说Linux Windows等等 92 00:04:16,000 --> 00:04:20,080 基本上也都是用了0和3这两个级别就够了 93 00:04:20,120 --> 00:04:26,400 这是我们说X86特权级的一个情况 94 00:04:26,440 --> 00:04:30,360 那我们说有一些指令它只能在ring 0里面执行 95 00:04:30,400 --> 00:04:34,560 而这些指令是X86的一些特权指令 96 00:04:34,600 --> 00:04:37,160 那这些指令一般也是我们操作系统来完成的 97 00:04:37,200 --> 00:04:38,800 那我们应用程序 98 00:04:38,840 --> 00:04:41,160 如果它一开始运行在用户态的时候 99 00:04:41,200 --> 00:04:44,600 如果它要去执行这些特权指令 100 00:04:44,640 --> 00:04:48,240 比如我们说的修改页表 响应中断 101 00:04:48,280 --> 00:04:51,000 访问内核区域的数据的时候 102 00:04:51,040 --> 00:04:53,200 比如我们说访问数据段 访问页表 103 00:04:53,240 --> 00:04:56,200 还有访问中断服务例程去执行的时候 104 00:04:56,240 --> 00:04:59,280 那就会产生异常 我们前面讲到 105 00:04:59,320 --> 00:05:02,640 有中断 有异常 这是说的产生异常 106 00:05:02,680 --> 00:05:05,800 产生异常之后就会阻止你继续执行 107 00:05:05,840 --> 00:05:08,080 这是一种典型的保护机制 108 00:05:08,120 --> 00:05:10,920 那么它是靠我们操作系统会做一个设置 109 00:05:10,960 --> 00:05:15,640 在我们CPU这个硬件的管理之下来确保 110 00:05:15,680 --> 00:05:18,160 我们的一般的应用程序处在 111 00:05:18,200 --> 00:05:20,400 我们刚才说的处于ring 3 112 00:05:20,440 --> 00:05:22,600 属于一般的特权级的情况下 113 00:05:22,640 --> 00:05:25,960 它无法去访问ring 0下面的一些 114 00:05:26,000 --> 00:05:28,400 所可以使用的一些特权指令 115 00:05:28,440 --> 00:05:30,600 和对应的那些数据等等 116 00:05:30,640 --> 00:05:32,800 117 00:05:32,840 --> 00:05:35,800 那前面我们看到CPU在很多情况下 118 00:05:35,840 --> 00:05:39,000 会做特权级检查 具体它怎么来做的 119 00:05:39,040 --> 00:05:40,800 我们需要进一步去了解一下细节 120 00:05:40,840 --> 00:05:42,880 接下来我们会接下来给大家介绍一下 121 00:05:42,920 --> 00:05:46,360 包括选择子以及后面的描述符 122 00:05:46,400 --> 00:05:48,040 怎么结合在一起来完成 123 00:05:48,080 --> 00:05:50,720 这一条指令执行的特权级检查 124 00:05:50,760 --> 00:05:52,160 那么为什么要这么做的呢 125 00:05:52,200 --> 00:05:53,280 我们其实很重要的一点就是 126 00:05:53,320 --> 00:05:56,240 我们在完成lab1 lab2以及后续的lab的时候 127 00:05:56,280 --> 00:05:58,440 经常会出现各种各样的错误 128 00:05:58,480 --> 00:06:00,000 而这些错误有一大部分情况 129 00:06:00,040 --> 00:06:01,400 是跟特权级相关的 130 00:06:01,440 --> 00:06:03,160 你如果理解了为什么会产生 131 00:06:03,200 --> 00:06:05,360 这些异常或者错误 132 00:06:05,400 --> 00:06:07,920 那么你就可以知道到底哪些地方你写错了 133 00:06:07,960 --> 00:06:11,400 所以说我们这边需要了解内部CPU 134 00:06:11,440 --> 00:06:14,040 是怎么来完成这个特权级检查的 135 00:06:14,080 --> 00:06:15,160 我们首先介绍个概念 136 00:06:15,200 --> 00:06:17,120 第一个概念是什么呢 段选择子 137 00:06:17,160 --> 00:06:20,840 段选择子是位于我们的段寄存器里面的 138 00:06:20,880 --> 00:06:22,600 那么我们可以说一个段 139 00:06:22,640 --> 00:06:24,400 有代码段 有数据段 140 00:06:24,440 --> 00:06:27,560 也意味着你的程序在代码段里执行 141 00:06:27,600 --> 00:06:30,280 你的数据位于数据段空间中 142 00:06:30,320 --> 00:06:33,240 那么一条指令去执行 它就会去访问 143 00:06:33,280 --> 00:06:35,080 我们的代码段和数据段 144 00:06:35,120 --> 00:06:39,360 而这个RPL以及后续讲到的CPL 145 00:06:39,400 --> 00:06:41,200 它其实就是一个位于数据段 146 00:06:41,240 --> 00:06:42,400 一个位于代码段 147 00:06:42,440 --> 00:06:45,280 合在一起再和我们段描述符里面 148 00:06:45,320 --> 00:06:47,560 所对应的DPL进行比较 149 00:06:47,600 --> 00:06:48,680 有点复杂 没关系 150 00:06:48,720 --> 00:06:51,640 大家可以逐步来看一下是怎么一回事 151 00:06:51,680 --> 00:06:52,920 首先我们介绍的段选择子 152 00:06:52,960 --> 00:06:55,520 这个段选择子第二步我们可以看到 153 00:06:55,560 --> 00:06:58,080 它的DPL是位于什么呢 154 00:06:58,120 --> 00:07:00,960 段描述符里面的 段描述符是什么东西 155 00:07:01,000 --> 00:07:02,080 我们前面已经讲到过 156 00:07:02,120 --> 00:07:05,280 段描述符是用来表示一个段的特征的 157 00:07:05,320 --> 00:07:07,520 一个很重要的数据信息 158 00:07:07,560 --> 00:07:10,320 我们这里面关注的跟特级权相关的 159 00:07:10,360 --> 00:07:11,240 包括了一个DPL 160 00:07:11,280 --> 00:07:14,000 就是跟这个段所相关的一个特权级 161 00:07:14,040 --> 00:07:14,760 我们也看到了 162 00:07:14,800 --> 00:07:17,160 前面说我们一项指令要访问一个段 163 00:07:17,200 --> 00:07:19,120 那这个代表了这一个段 164 00:07:19,160 --> 00:07:20,600 这一个数据段或者代码段 165 00:07:20,640 --> 00:07:22,040 它特级权是什么样的 166 00:07:22,080 --> 00:07:24,520 也意味着它前面讲的RPL和 167 00:07:24,560 --> 00:07:26,120 这里面的DPL做一个比较 168 00:07:26,160 --> 00:07:28,400 看这个特权级是否符合 169 00:07:28,440 --> 00:07:29,240 很简单一个想法 170 00:07:29,280 --> 00:07:30,920 就是我要去访问某一个数据 171 00:07:30,960 --> 00:07:32,120 首先我的特权级要足够高 172 00:07:32,160 --> 00:07:34,040 我才能访问某一个数据 173 00:07:34,080 --> 00:07:35,600 那你的特权级在什么地方呢 174 00:07:35,640 --> 00:07:36,760 175 00:07:36,800 --> 00:07:38,000 那么大家可以看到 176 00:07:38,040 --> 00:07:41,160 其实我们在前面lab1中已经提到过有中断 177 00:07:41,200 --> 00:07:42,160 我们讲过中断 178 00:07:42,200 --> 00:07:44,280 那中断 异常 陷入 179 00:07:44,320 --> 00:07:47,920 其实都还是需要通过一定的特权级检查 180 00:07:47,960 --> 00:07:49,800 所以在里面中断门 181 00:07:49,840 --> 00:07:51,800 中断门是我们说前面讲到的 182 00:07:51,840 --> 00:07:53,840 中断描述符表里面的重要组成部分 183 00:07:53,880 --> 00:07:57,640 中断门 陷入门里面 它都有对应的DPL 184 00:07:57,680 --> 00:08:00,400 这也是用来表明这个中断和 185 00:08:00,440 --> 00:08:04,400 对应的陷入大致特权级的展现 186 00:08:04,440 --> 00:08:07,040 187 00:08:07,080 --> 00:08:08,000 我们前面已经讲到了 188 00:08:08,040 --> 00:08:11,280 有段描述符 有中断门 有陷入门 189 00:08:11,320 --> 00:08:13,960 那么这几个它们都有对应的DPL 190 00:08:14,000 --> 00:08:15,480 而我们在产生中断 191 00:08:15,520 --> 00:08:17,920 或者完成一次内存访问的时候 192 00:08:17,960 --> 00:08:21,000 都会有对应的CPL和RPL 193 00:08:21,040 --> 00:08:22,760 那么这个CPL RPL和DPL之间 194 00:08:22,800 --> 00:08:26,080 有一个对应的特权级检查 从而可以确保 195 00:08:26,120 --> 00:08:30,760 当前这个操作是否会产生特权级的一个错误 196 00:08:30,800 --> 00:08:32,560 或者能够正常的通过特权级的检查 197 00:08:32,600 --> 00:08:36,120 能够继续完成相应的操作 这就是我们说 198 00:08:36,160 --> 00:08:39,320 这个特权级检查里面需要考虑的问题 199 00:08:39,360 --> 00:08:41,320 200 00:08:41,360 --> 00:08:44,120 我们看看怎么来比较 201 00:08:44,160 --> 00:08:47,560 我们知道RPL DPL和CPL 202 00:08:47,600 --> 00:08:51,120 我们是讲三个概念 RPL是处于数据段 203 00:08:51,160 --> 00:08:55,240 比如说我们的DS ES FS和GS 204 00:08:55,280 --> 00:08:58,200 那么它这里面是存了一个RPL 205 00:08:58,240 --> 00:09:02,320 是当前你要访问的数据段对应的特权级 206 00:09:02,360 --> 00:09:06,120 就是RPL 第二个你执行这条指令 207 00:09:06,160 --> 00:09:07,680 指令有个所谓的代码段 208 00:09:07,720 --> 00:09:09,120 那么指令的代码段存在哪呢 209 00:09:09,160 --> 00:09:11,400 CS里面 CS里面对应了一个CPL 210 00:09:11,440 --> 00:09:13,920 就是当前的一个代码段的一个特权级 211 00:09:13,960 --> 00:09:16,880 这个就是CPL 那么也意味着我们一条指令 212 00:09:16,920 --> 00:09:18,800 要访问一个数据段的时候 213 00:09:18,840 --> 00:09:21,640 它有两个特权级的表示 214 00:09:21,680 --> 00:09:24,680 一个是当前的特权级CPL 215 00:09:24,720 --> 00:09:27,480 位于CS的最低两位 216 00:09:27,520 --> 00:09:31,960 第二个是对应的要访问的数据段的RPL 217 00:09:32,000 --> 00:09:34,240 也是处于对应的ES或者FS等等 218 00:09:34,280 --> 00:09:36,560 它那个低两位有个RPL 219 00:09:36,600 --> 00:09:40,160 这两个占了两个bit和前面说的X86里面的 220 00:09:40,200 --> 00:09:42,560 四级特权级是一一对应的 221 00:09:42,600 --> 00:09:45,640 那就是0到3 0代表最高的优先级 222 00:09:45,680 --> 00:09:48,800 数值越低特权级越高 数值越高特权级越低 223 00:09:48,840 --> 00:09:52,280 正好是倒过来的 那这是发出请求的一方 224 00:09:52,320 --> 00:09:57,600 另一方面我们说你要访问的那个段 225 00:09:57,640 --> 00:10:00,160 无论是通过中断访问代码段 226 00:10:00,200 --> 00:10:03,080 还是通过内存访问 访问数据段 227 00:10:03,120 --> 00:10:05,640 它都会有一个那个段的描述 228 00:10:05,680 --> 00:10:06,960 就是无论是门还是段 229 00:10:07,000 --> 00:10:08,920 它都有一个所谓的DPL 230 00:10:08,960 --> 00:10:10,160 这个DPL代表了 231 00:10:10,200 --> 00:10:12,920 你要访问的目标它的特权级 232 00:10:12,960 --> 00:10:15,280 这个在什么情况下 233 00:10:15,320 --> 00:10:18,000 RPL CPL 和DPL处于什么关系的时候 234 00:10:18,040 --> 00:10:19,760 这个访问是合法的 235 00:10:19,800 --> 00:10:21,800 哪些情况是访问的不合法的 236 00:10:21,840 --> 00:10:24,000 这是我们说CPU检查的时候 237 00:10:24,040 --> 00:10:26,080 需要重点考虑的内容 238 00:10:26,120 --> 00:10:28,040 239 00:10:28,080 --> 00:10:29,920 其实这个检查是挺简单的 240 00:10:29,960 --> 00:10:33,160 大家可以看看 有两种情况 241 00:10:33,200 --> 00:10:36,200 一种是针对我们说的中断 陷入 异常 242 00:10:36,240 --> 00:10:38,120 这种情况称之为门情况 243 00:10:38,160 --> 00:10:40,920 访问门的时候 它需要做两个判断 244 00:10:40,960 --> 00:10:45,720 它当前的代码段CPL要小于门所处于的DPL 245 00:10:45,760 --> 00:10:48,600 也意味着这个门的特权级要比较低 246 00:10:48,640 --> 00:10:51,280 而我当前执行的代码段要比较高 247 00:10:51,320 --> 00:10:53,080 这样才允许通过门 248 00:10:53,120 --> 00:10:56,040 第二个CPL要大于等于DPL 249 00:10:56,080 --> 00:10:58,440 这什么意思呢 通过门之后目的是什么呢 250 00:10:58,480 --> 00:11:01,040 是要我们去访问特权级更高的段 251 00:11:01,080 --> 00:11:03,320 有了这个约束之后 252 00:11:03,360 --> 00:11:06,400 其实就可以实现我们的应用程序 253 00:11:06,440 --> 00:11:08,160 一般的特权级的应用程序 254 00:11:08,200 --> 00:11:10,600 就是我们说处于ring 3特权级的应用程序 255 00:11:10,640 --> 00:11:15,200 可以访问处于内核态的操作系统提供的服务 256 00:11:15,240 --> 00:11:17,440 这属于特权级ring 0的这个操作系统的服务 257 00:11:17,480 --> 00:11:19,840 就是从低优先级的可以访问高优先级的代码 258 00:11:19,880 --> 00:11:22,720 这是说通过我们说的中断门 259 00:11:22,760 --> 00:11:26,160 陷阱门或者陷入门可以完成这个功能 260 00:11:26,200 --> 00:11:29,000 那么在我们后续的lab5中 261 00:11:29,040 --> 00:11:30,680 有应用程序的时候就可以看到这一点 262 00:11:30,720 --> 00:11:33,080 我们用户态的进程可以通过这种方式 263 00:11:33,120 --> 00:11:34,160 通过系统调用的方式 264 00:11:34,200 --> 00:11:36,240 来获得我们操作系统的服务 265 00:11:36,280 --> 00:11:38,440 从用户态切换到内核态 266 00:11:38,480 --> 00:11:40,320 后续也会给大家进一步的讲解 267 00:11:40,360 --> 00:11:43,320 第二个是关于访问段的一个表述 268 00:11:43,360 --> 00:11:45,920 对于访问段而言也一样 269 00:11:45,960 --> 00:11:47,880 我们说我们当前的代码段 270 00:11:47,920 --> 00:11:49,040 和我们要访问的这个数据段 271 00:11:49,080 --> 00:11:51,240 我们发出的数据段特权级的请求 272 00:11:51,280 --> 00:11:56,120 一定要小于等于DPL这个段 273 00:11:56,160 --> 00:11:58,840 那么这意味着什么呢 这意味着说 274 00:11:58,880 --> 00:12:01,320 当前发出请求的这一方 275 00:12:01,360 --> 00:12:03,760 就是当前处于代码段执行这条指令 276 00:12:03,800 --> 00:12:06,360 它发出请求 我当前处于这种状态 277 00:12:06,400 --> 00:12:08,840 我要去访问某一个数据段 278 00:12:08,880 --> 00:12:14,360 那么我本身的特权级要高于对应的目标 279 00:12:14,400 --> 00:12:16,120 你作为使用方 280 00:12:16,160 --> 00:12:18,120 我的特权级要比较高一点我才能访问 281 00:12:18,160 --> 00:12:19,640 那么对应的数值的比较呢 282 00:12:19,680 --> 00:12:21,320 说就是小于等于 283 00:12:21,360 --> 00:12:24,120 就是CPL和RPL最大的一个值 284 00:12:24,160 --> 00:12:25,920 就是最低那个权限 285 00:12:25,960 --> 00:12:31,440 要高于它所对应的目标的那个段的特权级 286 00:12:31,480 --> 00:12:33,360 我们这里面数值上是小 287 00:12:33,400 --> 00:12:35,600 在实际特权级比较上是高 288 00:12:35,640 --> 00:12:38,080 这点正好是倒过来的 所以是小于等于 289 00:12:38,120 --> 00:12:39,960 那么有了这两个表示之后 290 00:12:40,000 --> 00:12:41,720 如果说它能够通过这个检查 291 00:12:41,760 --> 00:12:44,840 也就意味着它的特权级的检查是合格的 292 00:12:44,880 --> 00:12:46,600 那么我们这个指令可以正常去访问 293 00:12:46,640 --> 00:12:50,360 如果通不过就会产生所谓的保护错 294 00:12:50,400 --> 00:12:51,600 也是一种异常 295 00:12:51,640 --> 00:12:57,200 296 00:12:57,240 --> 00:12:58,160 297 00:12:58,200 --> 00:12:58,960 298 00:12:59,000 --> 00:12:59,680 299 00:12:59,720 --> 00:13:00,240 300 00:13:00,280 --> 00:13:00,320