0 00:00:00,000 --> 00:00:15,560 1 00:00:15,600 --> 00:00:17,600 好 各位同学大家好 2 00:00:17,640 --> 00:00:19,960 今天呢我们给大家介绍一下 3 00:00:20,000 --> 00:00:22,600 lab5就是用户进程的管理 4 00:00:22,640 --> 00:00:24,880 那这一部分呢 可以看到 5 00:00:24,920 --> 00:00:26,480 我们主要讲以下几部分内容 6 00:00:26,520 --> 00:00:28,560 第一个是总体介绍 7 00:00:28,600 --> 00:00:29,880 大家知道我们这个实验 8 00:00:29,920 --> 00:00:31,120 大致要完成什么样的功能 9 00:00:31,160 --> 00:00:33,400 以及相应的一些总体的一些概述 10 00:00:33,440 --> 00:00:34,400 第二个呢是 11 00:00:34,440 --> 00:00:36,160 关于我们创建个用户进程 12 00:00:36,200 --> 00:00:38,160 它的内存布局怎么回事 13 00:00:38,200 --> 00:00:39,720 和我们前面讲有点不太一样 14 00:00:39,760 --> 00:00:41,120 这是给大家做个介绍 15 00:00:41,160 --> 00:00:42,200 第三个呢 16 00:00:42,240 --> 00:00:43,600 我们既然要创建个用户进程 17 00:00:43,640 --> 00:00:45,320 就需要执行一定的程序 18 00:00:45,360 --> 00:00:46,680 那怎么能够把一个程序 19 00:00:46,720 --> 00:00:48,280 放在进程里面去执行 20 00:00:48,320 --> 00:00:49,760 这是这部分内容 21 00:00:49,800 --> 00:00:52,480 以及我们说在原理课里面讲到 22 00:00:52,520 --> 00:00:55,160 可以通过父进程创建子进程 23 00:00:55,200 --> 00:00:56,920 那么具体这个进程复制 24 00:00:56,960 --> 00:00:58,320 是怎么完成的 25 00:00:58,360 --> 00:00:59,520 也会给大家做个介绍 26 00:00:59,560 --> 00:01:01,000 最后一部分呢 27 00:01:01,040 --> 00:01:02,800 是一个比较扩展一个内容 28 00:01:02,840 --> 00:01:04,200 也是我们challenge的练习 29 00:01:04,240 --> 00:01:05,880 就是怎么能够结合 30 00:01:05,920 --> 00:01:07,720 内存管理的copy on write机制 31 00:01:07,760 --> 00:01:10,360 来实现更有效的进程复制 32 00:01:10,400 --> 00:01:12,480 这是我们这次总体 33 00:01:12,520 --> 00:01:15,760 要介绍的一部分内容 34 00:01:15,800 --> 00:01:19,200 首先看一下这个总体介绍 35 00:01:19,240 --> 00:01:20,160 那么其实包含了 36 00:01:20,200 --> 00:01:23,880 这次实验的目标练习和流程概述 37 00:01:23,920 --> 00:01:25,120 那我们的目标是什么呢 38 00:01:25,160 --> 00:01:27,120 其实我们希望通过这个练习呢 39 00:01:27,160 --> 00:01:30,200 大家能够知道我们前面的三个实验 40 00:01:30,240 --> 00:01:32,800 从lab1 2 3 41 00:01:32,840 --> 00:01:35,880 那么是介绍了中断和内存管理 42 00:01:35,920 --> 00:01:38,360 第四个实验已经有了内核线程 43 00:01:38,400 --> 00:01:40,280 但是所有这些实验呢 44 00:01:40,320 --> 00:01:41,120 都在什么地方呢 45 00:01:41,160 --> 00:01:42,400 都是在内核空间里面来 46 00:01:42,440 --> 00:01:43,680 完成各种各样的工程 47 00:01:43,720 --> 00:01:45,640 还没有碰到像我们说 48 00:01:45,680 --> 00:01:47,080 像这次实验课我们会提到什么 49 00:01:47,120 --> 00:01:49,360 你要创建一个在用户态 50 00:01:49,400 --> 00:01:51,480 执行的一个进程 51 00:01:51,520 --> 00:01:52,600 那这个呢是 52 00:01:52,640 --> 00:01:53,840 第一次我们的实验 53 00:01:53,880 --> 00:01:55,880 从内核态跳到了用户态 54 00:01:55,920 --> 00:01:57,360 那我们也就希望能够 55 00:01:57,400 --> 00:01:59,600 把这个过程给大家展示出来 56 00:01:59,640 --> 00:02:02,560 通过前面的lab1到lab4的工作呢 57 00:02:02,600 --> 00:02:03,800 我们在lab空间里面 58 00:02:03,840 --> 00:02:06,200 可以创建一系列的线程 59 00:02:06,240 --> 00:02:10,120 最后来构造出一个用户态的进程 60 00:02:10,160 --> 00:02:11,960 让它能够在用户空间去执行 61 00:02:12,000 --> 00:02:18,320 这是说我们这次课希望达到一个目标 62 00:02:18,360 --> 00:02:19,760 那把这个目标细化一下 63 00:02:19,800 --> 00:02:21,520 我们这边要了解什么呢 64 00:02:21,560 --> 00:02:23,800 第一个就是要了解一下 65 00:02:23,840 --> 00:02:25,720 一个用户进程的创建过程 66 00:02:25,760 --> 00:02:27,640 他怎么从零变到一的 67 00:02:27,680 --> 00:02:30,720 从没有用户的进程到 68 00:02:30,760 --> 00:02:32,680 存在用户进程怎么创建出来的 69 00:02:32,720 --> 00:02:34,640 鸡和蛋怎么出现的 70 00:02:34,680 --> 00:02:37,760 第二个呢是了解进程管理的实现 71 00:02:37,800 --> 00:02:39,400 这里面主要是讲的是什么 72 00:02:39,440 --> 00:02:41,200 主要是说我们怎么能够让 73 00:02:41,240 --> 00:02:42,600 一个程序的内容能够 74 00:02:42,640 --> 00:02:45,040 放到一个进程里面去执行 75 00:02:45,080 --> 00:02:46,640 那这里面要了解什么是程序 76 00:02:46,680 --> 00:02:47,360 什么是进程 77 00:02:47,400 --> 00:02:48,680 它们之间的区别是什么 78 00:02:48,720 --> 00:02:50,200 在原理课里面给大家做了介绍 79 00:02:50,240 --> 00:02:51,960 那么通过实验呢 80 00:02:52,000 --> 00:02:53,560 希望大家能够加强对 81 00:02:53,600 --> 00:02:56,240 这两者之间的这个关系 82 00:02:56,280 --> 00:02:58,520 和差别的理解 83 00:02:58,560 --> 00:02:59,600 第三个是要了解 84 00:02:59,640 --> 00:03:00,960 系统调用框架的实现 85 00:03:01,000 --> 00:03:03,760 那这个和前面两个不太一样 86 00:03:03,800 --> 00:03:06,040 前面两个需要大家去coding 87 00:03:06,080 --> 00:03:07,680 需要去动手实验一下 88 00:03:07,720 --> 00:03:08,840 那么对于最后这个呢 89 00:03:08,880 --> 00:03:10,360 是大家是看一下 90 00:03:10,400 --> 00:03:11,760 那么来看懂就OK了 91 00:03:11,800 --> 00:03:13,640 相对来说我们的重点是放在前面 92 00:03:13,680 --> 00:03:15,560 这个虽然很重要 93 00:03:15,600 --> 00:03:17,240 因为通过系统调用呢 94 00:03:17,280 --> 00:03:18,920 我们可以实现用户进程 95 00:03:18,960 --> 00:03:20,280 得到内核的服务 96 00:03:20,320 --> 00:03:21,400 但这一块呢 97 00:03:21,440 --> 00:03:22,400 只要大家能看懂就OK了 98 00:03:22,440 --> 00:03:24,800 因为对于系统调用的 99 00:03:24,840 --> 00:03:25,840 这一部分的内容呢 100 00:03:25,880 --> 00:03:27,760 其实和我们lab1中断管理呢 101 00:03:27,800 --> 00:03:29,520 是有很紧密的联系的 102 00:03:29,560 --> 00:03:32,040 它们有很大的一个相关性 103 00:03:32,080 --> 00:03:33,440 但是也有一定的区别 104 00:03:33,480 --> 00:03:36,480 那么你如果对lab1那个实验 105 00:03:36,520 --> 00:03:37,960 有充分的了解之后呢 106 00:03:38,000 --> 00:03:39,600 再看系统调用它的实现 107 00:03:39,640 --> 00:03:41,280 其实是比较简单的 108 00:03:41,320 --> 00:03:43,560 那我们在前面内容里面也讲到了 109 00:03:43,600 --> 00:03:46,480 这个从一个特权级跳另一个特权级 110 00:03:46,520 --> 00:03:47,280 怎么来完成呢 111 00:03:47,320 --> 00:03:48,800 那其实也和我们这个 112 00:03:48,840 --> 00:03:50,520 中断管理机制是相关的 113 00:03:50,560 --> 00:03:53,080 那么大家可以回顾之前的一些工作呢 114 00:03:53,120 --> 00:03:57,040 可以对此有更深入的理解 115 00:03:57,080 --> 00:03:58,680 好 基于这个目标 116 00:03:58,720 --> 00:04:00,000 我们要完成练习也是一样的 117 00:04:00,040 --> 00:04:02,240 正好是说我们要去coding 118 00:04:02,280 --> 00:04:04,000 去加载应用程序并执行 119 00:04:04,040 --> 00:04:04,880 那么要去理解它大致 120 00:04:04,920 --> 00:04:08,200 加载执行的这个过程怎么回事 121 00:04:08,240 --> 00:04:10,680 然后完成我们需要完成的一个功能 122 00:04:10,720 --> 00:04:12,280 第二个呢 我们要考虑一下 123 00:04:12,320 --> 00:04:14,760 父进程怎么去复制子进程 124 00:04:14,800 --> 00:04:17,840 这里面要考虑的一些细节问题呢 125 00:04:17,880 --> 00:04:18,640 在原理课里面 126 00:04:18,680 --> 00:04:19,600 可能涉及的比较少一点 127 00:04:19,640 --> 00:04:21,280 我们希望通过实验呢 128 00:04:21,320 --> 00:04:23,000 能够知道这里面的细节 129 00:04:23,040 --> 00:04:24,200 是怎么来完成的 130 00:04:24,240 --> 00:04:25,800 怎么来通过父进程 131 00:04:25,840 --> 00:04:28,760 能够创建出一个子进程出来 132 00:04:28,800 --> 00:04:30,560 第三个呢 是要分析系统调用 133 00:04:30,600 --> 00:04:32,640 和进程管理的实现 134 00:04:32,680 --> 00:04:34,680 因为我们知道我们的用户进程呢 135 00:04:34,720 --> 00:04:35,920 它需要通过系统调用 136 00:04:35,960 --> 00:04:37,680 来得到操作系统服务 137 00:04:37,720 --> 00:04:39,040 这是一个 第二个呢 138 00:04:39,080 --> 00:04:40,720 操作系统对进程本身也有管理 139 00:04:40,760 --> 00:04:43,680 从最开始的创建到最后进程的消失 140 00:04:43,720 --> 00:04:45,200 这有个生命周期的管理 141 00:04:45,240 --> 00:04:46,760 在原理课里面也讲过 142 00:04:46,800 --> 00:04:49,080 那我们会通过阅读代码呢 143 00:04:49,120 --> 00:04:50,800 能对此有更深入体会 144 00:04:50,840 --> 00:04:52,240 那我们的重点放在前面 145 00:04:52,280 --> 00:04:54,880 前面是你怎么知道创建一个进程 146 00:04:54,920 --> 00:04:57,160 当你知道怎么去创建一个进程之后呢 147 00:04:57,200 --> 00:04:58,760 那么后续的一些工作 148 00:04:58,800 --> 00:05:01,160 比如说进程状态的改变 149 00:05:01,200 --> 00:05:02,800 相对来说比较简单一点 150 00:05:02,840 --> 00:05:04,800 还有一个呢进程的卸载 151 00:05:04,840 --> 00:05:06,680 比如说我们进程的离开退出 152 00:05:06,720 --> 00:05:07,800 那么这个呢 153 00:05:07,840 --> 00:05:08,680 相对来说就是 154 00:05:08,720 --> 00:05:10,280 我们前面创建过程的一个逆过程 155 00:05:10,320 --> 00:05:12,480 所以说也比较容易理解 156 00:05:12,520 --> 00:05:14,960 这就是练习希望达到的目标 157 00:05:15,000 --> 00:05:18,640 OK 那大家听起来好像感觉还不够 158 00:05:18,680 --> 00:05:20,720 不知道到底跑什么程序 159 00:05:20,760 --> 00:05:22,000 其实很简单 160 00:05:22,040 --> 00:05:23,640 可以看到这个所谓的hello应用程序 161 00:05:23,680 --> 00:05:27,040 和我们通常写的简单hello world很类似 162 00:05:27,080 --> 00:05:27,960 没啥区别 163 00:05:28,000 --> 00:05:29,800 这也是我们在ucore操作系统里面 164 00:05:29,840 --> 00:05:32,960 支持跑的一个简单的应用程序 165 00:05:33,000 --> 00:05:35,360 你可以看出来他干什么事情呢 166 00:05:35,400 --> 00:05:38,160 一个main函数它就是打印字符串 167 00:05:38,200 --> 00:05:41,920 第二个呢有系统调用叫getpid() 168 00:05:41,960 --> 00:05:45,160 就得到当前它这个进程的ID信息 169 00:05:45,200 --> 00:05:46,720 然后就退出了 170 00:05:46,760 --> 00:05:48,880 从创建到最后return之后呢 171 00:05:48,920 --> 00:05:51,480 我们的操作系统会把它给它kill掉 172 00:05:51,520 --> 00:05:52,720 让它退出出去 173 00:05:52,760 --> 00:05:55,160 那这里面就包含了系统调用 174 00:05:55,200 --> 00:05:58,040 包含了创建一个基于 175 00:05:58,080 --> 00:06:00,440 这个内容的一个用户进程 176 00:06:00,480 --> 00:06:02,760 它的一个执行的一个状态的管理 177 00:06:02,800 --> 00:06:05,160 以及最后生命周期一个管理退出 178 00:06:05,200 --> 00:06:07,120 虽然这个程序很小 179 00:06:07,160 --> 00:06:09,040 但是ucore操作系统呢 180 00:06:09,080 --> 00:06:10,880 对它的管理是全面的 181 00:06:10,920 --> 00:06:12,120 我们希望大家能够对这个 182 00:06:12,160 --> 00:06:16,360 管理过程能够比较清楚的认识 183 00:06:16,400 --> 00:06:19,680 好 那这个整个这个实验 184 00:06:19,720 --> 00:06:21,080 我们说lab5的实验 185 00:06:21,120 --> 00:06:22,720 我们最主要说要给应用程序 186 00:06:22,760 --> 00:06:26,040 需要提供一个用户态的运行空间 187 00:06:26,080 --> 00:06:28,800 那这个呢其实包含了两部分内容 188 00:06:28,840 --> 00:06:29,840 一部分什么呢 189 00:06:29,880 --> 00:06:31,560 一部分是内存管理 190 00:06:31,600 --> 00:06:32,840 一个进程要运行 191 00:06:32,880 --> 00:06:33,880 那必须要有个内存空间它所 192 00:06:33,920 --> 00:06:37,040 运行所需要的代码段 193 00:06:37,080 --> 00:06:38,160 数据段有内存空间 194 00:06:38,200 --> 00:06:39,880 它有个内存空间的管理 195 00:06:39,920 --> 00:06:43,640 和我们的lab2lab3有紧密的联系 196 00:06:43,680 --> 00:06:45,440 第二个呢 进程管理 197 00:06:45,480 --> 00:06:47,520 这也是我们这次实验的重点 198 00:06:47,560 --> 00:06:49,080 但是我们已经有lab4 199 00:06:49,120 --> 00:06:51,280 其实已经有一部分的进程管理 200 00:06:51,320 --> 00:06:53,760 但是那时候我们叫内核线程 201 00:06:53,800 --> 00:06:55,360 进程和线程的关系是什么呢 202 00:06:55,400 --> 00:06:57,560 那么在原理课里面是讲过 203 00:06:57,600 --> 00:06:59,000 大家想一想 204 00:06:59,040 --> 00:07:00,840 进程和线程什么关系 205 00:07:00,880 --> 00:07:02,760 那么这里面多了一点不同在哪呢 206 00:07:02,800 --> 00:07:05,720 用户进程和内核线程 207 00:07:05,760 --> 00:07:08,080 它们之间的关系和区别是什么 208 00:07:08,120 --> 00:07:10,240 在这里面我们ucore操作系统呢 209 00:07:10,280 --> 00:07:13,440 对这个用户进程和内核线程呢 210 00:07:13,480 --> 00:07:16,160 有一套几乎统一一套管理体制 211 00:07:16,200 --> 00:07:17,720 但是它们有很大的区别 212 00:07:17,760 --> 00:07:20,160 那这里面我们希望通过完成 213 00:07:20,200 --> 00:07:22,080 lab4和lab5呢对 214 00:07:22,120 --> 00:07:25,840 这两者有更清楚的认识 215 00:07:25,880 --> 00:07:26,920 对于内存管理而言 216 00:07:26,960 --> 00:07:28,040 我们还需要知道 217 00:07:28,080 --> 00:07:30,280 怎么去创建一个用户态的虚拟空间 218 00:07:30,320 --> 00:07:33,280 我们之前的实验都是在内核里面 219 00:07:33,320 --> 00:07:34,960 创建内核态的虚拟空间 220 00:07:35,000 --> 00:07:35,880 那这里面不一样 221 00:07:35,920 --> 00:07:37,760 我们要新增一个用户态虚拟空间 222 00:07:37,800 --> 00:07:41,120 这需要去了解的 223 00:07:41,160 --> 00:07:42,400 对于进程管理而言呢 224 00:07:42,440 --> 00:07:44,600 我们需要知道怎么去加载 225 00:07:44,640 --> 00:07:45,640 一个应用程序到 226 00:07:45,680 --> 00:07:47,160 这个进程空间里面去 227 00:07:47,200 --> 00:07:48,360 怎么去复制 228 00:07:48,400 --> 00:07:49,920 怎么去创建新的子进程 229 00:07:49,960 --> 00:07:50,800 就所谓的复制 230 00:07:50,840 --> 00:07:52,120 我们叫fork 231 00:07:52,160 --> 00:07:53,960 第三个呢 怎么去管理 232 00:07:54,000 --> 00:07:55,680 整个进程的生命周期 233 00:07:55,720 --> 00:07:57,240 第四个怎么让进程得到 234 00:07:57,280 --> 00:07:58,400 操作系统服务 235 00:07:58,440 --> 00:07:59,960 这是进程管理的功能 236 00:08:00,000 --> 00:08:02,240 那么这一部分内容呢也是新的 237 00:08:02,280 --> 00:08:04,360 那么也是在我们的lab5中 238 00:08:04,400 --> 00:08:06,280 希望通过实现 239 00:08:06,320 --> 00:08:09,280 实现相应的一些练习和阅读代码呢 240 00:08:09,320 --> 00:08:10,200 能够对这些内容呢 241 00:08:10,240 --> 00:08:15,200 有一个比较清楚的理解 242 00:08:15,240 --> 00:08:17,480 那我们可以简单的看一下 243 00:08:17,520 --> 00:08:20,800 怎么在lab5中构造出一个用户进程 244 00:08:20,840 --> 00:08:22,920 它的流程大致这样的 245 00:08:22,960 --> 00:08:25,480 首先我们要创建用户代码段 246 00:08:25,520 --> 00:08:26,960 和用户的数据段 247 00:08:27,000 --> 00:08:29,440 那么这对我们的lab几 248 00:08:29,480 --> 00:08:30,440 大家想一想 249 00:08:30,480 --> 00:08:31,840 对我们lab1中的 250 00:08:31,880 --> 00:08:33,880 段机制的管理呢做了一个扩展 251 00:08:33,920 --> 00:08:34,960 我们在lab1中 252 00:08:35,000 --> 00:08:38,480 只讲到了内核的代码段和数据段 253 00:08:38,520 --> 00:08:39,840 那这里面多了两个 254 00:08:39,880 --> 00:08:41,720 用户的代码段和数据段 255 00:08:41,760 --> 00:08:43,080 这里面有个扩充 256 00:08:43,120 --> 00:08:44,720 有扩充之后呢 257 00:08:44,760 --> 00:08:47,520 第二步呢我们能够创建内核线程 258 00:08:47,560 --> 00:08:50,760 这一点是在lab4中完成了 259 00:08:50,800 --> 00:08:52,000 创建内核线程的目的 260 00:08:52,040 --> 00:08:54,200 是为进一步创建用户进程做好准备 261 00:08:54,240 --> 00:08:56,920 所以说在这里面呢 262 00:08:56,960 --> 00:08:59,440 我们首先要创建用户进程的壳 263 00:08:59,480 --> 00:09:01,400 所谓创建它的壳呢就是说 264 00:09:01,440 --> 00:09:04,200 要能够创建一个进程的控制块 265 00:09:04,240 --> 00:09:05,960 以及进程控制块 266 00:09:06,000 --> 00:09:10,480 所管理的很多关键的一些数据 267 00:09:10,520 --> 00:09:12,160 比如说我举个简单例子 268 00:09:12,200 --> 00:09:13,840 后面看到它的ID 269 00:09:13,880 --> 00:09:15,760 它的执行状态等等 270 00:09:15,800 --> 00:09:17,640 这后面会进一步展开 271 00:09:17,680 --> 00:09:18,640 有了壳之后呢 272 00:09:18,680 --> 00:09:20,120 我们需要具体的执行内容 273 00:09:20,160 --> 00:09:21,080 这个内容从哪来呢 274 00:09:21,120 --> 00:09:22,080 是我们应用程序里面 275 00:09:22,120 --> 00:09:23,720 提供了它的具体执行 276 00:09:23,760 --> 00:09:26,400 比如前面讲的hello world小程序 277 00:09:26,440 --> 00:09:27,320 它有具体的执行内容 278 00:09:27,360 --> 00:09:28,400 我们把这个内容呢 279 00:09:28,440 --> 00:09:30,760 要放到这个进程里面去 280 00:09:30,800 --> 00:09:33,000 比如说这个进程的代码段的空间里面 281 00:09:33,040 --> 00:09:35,520 我们要把具体程序的内容放进去 282 00:09:35,560 --> 00:09:37,960 从而可以使得它可以进一步执行 283 00:09:38,000 --> 00:09:40,000 放进去之后呢 284 00:09:40,040 --> 00:09:41,560 就可以执行这个用户进程了 285 00:09:41,600 --> 00:09:44,040 但需要注意的是跟前面的不同在哪呢 286 00:09:44,080 --> 00:09:46,440 这个执行是在用户空间执行的 287 00:09:46,480 --> 00:09:48,520 不是在内核空间执行的 288 00:09:48,560 --> 00:09:50,880 这是我们前面四个实验没有碰到 289 00:09:50,920 --> 00:09:54,720 你怎么能够从内核态跳到用户态去 290 00:09:54,760 --> 00:09:57,280 这涉及到特权级的一个转换 291 00:09:57,320 --> 00:09:58,280 那在回顾一下 292 00:09:58,320 --> 00:09:59,960 我们在前面实验中专门讲过 293 00:10:00,000 --> 00:10:02,520 特权级它的特点是什么 294 00:10:02,560 --> 00:10:04,200 它怎么去实现转换的 295 00:10:04,240 --> 00:10:09,560 和我们中断管理机制有很紧密的联系 296 00:10:09,600 --> 00:10:11,480 在执行应用程序过程中 297 00:10:11,520 --> 00:10:13,920 它可能需要我们操作系统的服务 298 00:10:13,960 --> 00:10:15,280 为此呢我们需要去 299 00:10:15,320 --> 00:10:17,520 完成一个系统调用的一个管理机制 300 00:10:17,560 --> 00:10:19,320 从而可以实现怎么去有效 301 00:10:19,360 --> 00:10:21,160 我发这个请求 302 00:10:21,200 --> 00:10:24,640 怎么能得到操作系统有效的服务 303 00:10:24,680 --> 00:10:26,480 当用户进程执行完毕之后 304 00:10:26,520 --> 00:10:28,840 那我们操作系统需要 305 00:10:28,880 --> 00:10:31,080 把这个用户进程所占的资源 306 00:10:31,120 --> 00:10:33,840 比如内存空间等等给回收回来 307 00:10:33,880 --> 00:10:35,440 从而可以退出这个进程 308 00:10:35,480 --> 00:10:36,160 那么我们就要有 309 00:10:36,200 --> 00:10:37,920 结束用户进程管理体制 310 00:10:37,960 --> 00:10:39,360 这里面就涉及到 311 00:10:39,400 --> 00:10:40,400 进程的生命周期管理 312 00:10:40,440 --> 00:10:42,880 从最开始创建到最后的结束 313 00:10:42,920 --> 00:10:45,440 那么这就是整个我们说lab5里面 314 00:10:45,480 --> 00:10:48,520 会碰到的一些实验的一个过程 315 00:10:49,040 --> 00:10:49,080 316 00:10:49,120 --> 00:10:49,160