0 00:00:00,000 --> 00:00:15,520 1 00:00:15,600 --> 00:00:20,600 今天我们开始介绍进程和线程 2 00:00:20,640 --> 00:00:24,120 进程和线程呢实际上讨论的是 3 00:00:24,200 --> 00:00:26,120 操作系统在让一个程序 4 00:00:26,160 --> 00:00:27,240 执行的过程当中 5 00:00:27,280 --> 00:00:28,280 这个执行的过程 6 00:00:28,320 --> 00:00:29,960 我们是如何在维护的 7 00:00:30,000 --> 00:00:32,400 那今天呢我们首先来讲进程 8 00:00:32,440 --> 00:00:34,760 9 00:00:34,800 --> 00:00:36,400 在实际的操作系统当中 10 00:00:36,440 --> 00:00:37,520 我们有一组工具 11 00:00:37,560 --> 00:00:39,640 可以让你知道一个程序 12 00:00:39,680 --> 00:00:41,160 它执行的状态是什么样的 13 00:00:41,200 --> 00:00:43,880 比如说这个执行的是哪一个程序 14 00:00:43,920 --> 00:00:46,440 然后它目前占用内存是多少 15 00:00:46,480 --> 00:00:49,240 然后CPU的使用时间是多少 16 00:00:49,280 --> 00:00:51,440 那这地方都是它的相关信息 17 00:00:51,480 --> 00:00:52,640 那这时候有一个问题 18 00:00:52,680 --> 00:00:55,400 程序和程序的执行 19 00:00:55,440 --> 00:00:56,320 也就是我们这里说的 20 00:00:56,360 --> 00:00:58,800 进程它到底是什么样的关系 21 00:00:58,840 --> 00:01:00,080 22 00:01:00,120 --> 00:01:03,600 那我们首先呢对进程给一个定义 23 00:01:03,640 --> 00:01:08,120 进程是一个具有一定功能的程序 24 00:01:08,160 --> 00:01:10,800 在一个数据集上的一次动态的执行 25 00:01:10,840 --> 00:01:11,760 26 00:01:11,800 --> 00:01:14,520 那我们说程序肯定是具有功能的 27 00:01:14,560 --> 00:01:16,800 那我们在这里进程多加的两个属性 28 00:01:16,840 --> 00:01:20,480 是数据和动态执行 29 00:01:20,520 --> 00:01:22,080 有了这个程序 30 00:01:22,120 --> 00:01:24,160 加上数据和动态执行之后呢 31 00:01:24,200 --> 00:01:25,960 就变成我们的进程 32 00:01:26,000 --> 00:01:27,000 33 00:01:27,040 --> 00:01:29,920 那这是我们在前面讲的时候 34 00:01:29,960 --> 00:01:33,000 我写的程序那这是它的源代码 35 00:01:33,040 --> 00:01:35,400 然后源代码我们经过编译之后呢 36 00:01:35,440 --> 00:01:36,920 变成目标文件 37 00:01:36,960 --> 00:01:38,920 这时候有我们前面讲的地址的转换 38 00:01:38,960 --> 00:01:40,480 然后在加载的时候呢 39 00:01:40,520 --> 00:01:42,280 把它放到内存里头 40 00:01:42,320 --> 00:01:43,080 我们把一个程序 41 00:01:43,120 --> 00:01:44,920 放到内存里的目标是什么 42 00:01:44,960 --> 00:01:47,120 就是为了让它对数据进行处理 43 00:01:47,160 --> 00:01:48,440 让它能够执行 44 00:01:48,480 --> 00:01:51,960 那这就是我们这里头数据和执行 45 00:01:52,000 --> 00:01:54,600 那进程呢就是讨论这个 46 00:01:54,640 --> 00:01:56,760 程序在对数据进行处理的时候 47 00:01:56,800 --> 00:01:58,000 这个处理过程 48 00:01:58,040 --> 00:01:59,720 操作系统是如何维护的 49 00:01:59,760 --> 00:02:01,960 50 00:02:02,000 --> 00:02:04,920 那我们换个角度来看一下 51 00:02:04,960 --> 00:02:07,600 进程和程序之间的变化的内容 52 00:02:07,640 --> 00:02:09,480 这是我们的源代码 53 00:02:09,520 --> 00:02:12,080 你写出来的静态的程序 54 00:02:12,120 --> 00:02:14,520 好这个程序在被加到内存当中的 55 00:02:14,560 --> 00:02:16,360 我们首先以一种形式 56 00:02:16,400 --> 00:02:17,520 把它的代码放在这里头 57 00:02:17,560 --> 00:02:19,800 然后在这上面又加了一段 58 00:02:19,840 --> 00:02:24,640 这就是我们的 堆 栈 和数据 数据段 59 00:02:24,680 --> 00:02:25,760 这些内容呢实际上是为了 60 00:02:25,800 --> 00:02:26,880 让我这程序在执行的 61 00:02:26,920 --> 00:02:28,880 过程当中进行维护的 62 00:02:28,920 --> 00:02:30,560 比如说我这里有函数调用 63 00:02:30,600 --> 00:02:32,120 那函数调用和返回的地址呢 64 00:02:32,160 --> 00:02:33,960 就必须写到我的堆栈里头 65 00:02:34,000 --> 00:02:35,680 以便于我知道 66 00:02:35,720 --> 00:02:37,200 进到一个函数里头是从哪过去的 67 00:02:37,240 --> 00:02:39,880 回来的时候我要回到什么地方去 68 00:02:39,920 --> 00:02:41,440 那这是呢 69 00:02:41,480 --> 00:02:43,640 这个进程在和程序 70 00:02:43,680 --> 00:02:47,560 相比较而言我们加的内容 71 00:02:47,600 --> 00:02:51,120 那进程到底有些什么样的组成呢 72 00:02:51,160 --> 00:02:52,760 简单的来说进程包括 73 00:02:52,800 --> 00:02:55,000 程序执行的所有状态 74 00:02:55,040 --> 00:02:56,480 那具体说起来呢 75 00:02:56,520 --> 00:02:58,840 包括这样一些代码数据 76 00:02:58,880 --> 00:03:00,520 这是我们在前面提到过的 77 00:03:00,560 --> 00:03:01,960 但更多的呢是我们这里 78 00:03:02,000 --> 00:03:03,560 现在执行过程当中状态 79 00:03:03,600 --> 00:03:06,200 你比如状态寄存器通用寄存器 80 00:03:06,240 --> 00:03:08,360 和进程所占用的资源 81 00:03:08,400 --> 00:03:10,080 这些内容呢最后会构成 82 00:03:10,120 --> 00:03:10,920 我们在进程里一个 83 00:03:10,960 --> 00:03:14,640 很重要的组成部分叫进程控制块 84 00:03:14,680 --> 00:03:19,360 好这些内容呢搁到一起 85 00:03:19,400 --> 00:03:21,480 由于操作系统提供了进程概念 86 00:03:21,520 --> 00:03:23,200 好那我们进程在这里呢 87 00:03:23,240 --> 00:03:25,240 就体现出这样一些特征 88 00:03:25,280 --> 00:03:27,840 一种呢是动态性 89 00:03:27,880 --> 00:03:29,520 那说我的一个程序它在执行的过程当中 90 00:03:29,560 --> 00:03:32,600 有从创建到结束这个过程 91 00:03:32,640 --> 00:03:34,080 第二个呢是并发性 92 00:03:34,120 --> 00:03:36,960 那么我们通常所说的程序执行 93 00:03:37,000 --> 00:03:40,280 它只是一个指令指针在执行 94 00:03:40,320 --> 00:03:41,880 那我们有了操作系统之后 95 00:03:41,920 --> 00:03:45,360 这时候可以交替执行多个程序 96 00:03:45,400 --> 00:03:47,280 这个多个程序呢它可以在 97 00:03:47,320 --> 00:03:49,760 操作系统的调度下占用CPU来执行 98 00:03:49,800 --> 00:03:51,600 这种交替性呢就可以体现出 99 00:03:51,640 --> 00:03:54,520 我们在宏观上的一种并发性 100 00:03:54,560 --> 00:03:56,760 再有一个呢是独立性 101 00:03:56,800 --> 00:03:58,320 不同的进程呢我们希望 102 00:03:58,360 --> 00:04:00,600 它们之间的工作呢相互不影响 103 00:04:00,640 --> 00:04:02,960 这是它的独立性 104 00:04:03,000 --> 00:04:04,200 但是另外一个呢 105 00:04:04,240 --> 00:04:06,120 它还有一个特征叫制约性 106 00:04:06,160 --> 00:04:09,160 也就是说我两个或者多个进程 107 00:04:09,200 --> 00:04:11,920 在同一个操作系统下运行的时候 108 00:04:11,960 --> 00:04:14,440 它们就会由于共享数据 109 00:04:14,480 --> 00:04:18,440 或者说资源进程之间的通讯和 110 00:04:18,480 --> 00:04:21,280 同步产生相互之间制约 111 00:04:21,320 --> 00:04:22,360 这时候我们就需要有一个 112 00:04:22,400 --> 00:04:24,360 需要仔细把握的地方就是在于 113 00:04:24,400 --> 00:04:27,000 进程的独立性和制约性 114 00:04:27,040 --> 00:04:29,200 它们俩之间我怎么来权衡 115 00:04:29,240 --> 00:04:31,280 我们希望一个程序的执行是独立的 116 00:04:31,320 --> 00:04:33,480 但是我们同时也希望一个程序 117 00:04:33,520 --> 00:04:36,480 在执行过程中能够跟外界打交道 118 00:04:36,520 --> 00:04:37,800 这样的话我才能用同一个程序 119 00:04:37,840 --> 00:04:40,280 对不同的数据进行处理 120 00:04:40,320 --> 00:04:41,480 好那下边呢我们通过 121 00:04:41,520 --> 00:04:43,440 这样一个图示来说程序进程 122 00:04:43,480 --> 00:04:48,000 和我们在原来的CPU上执行的程序 123 00:04:48,040 --> 00:04:52,440 它怎么就体现出上面这几个特征来 124 00:04:52,480 --> 00:04:55,680 那我们这地方看到这条线索呢 125 00:04:55,720 --> 00:04:58,400 你可以理解为进程CPU 126 00:04:58,440 --> 00:05:01,440 在执行指令的时候的情况 127 00:05:01,480 --> 00:05:02,720 执行进程A的指令 128 00:05:02,760 --> 00:05:04,600 然后切换到进程B 129 00:05:04,640 --> 00:05:06,000 执行进程B的指令 130 00:05:06,040 --> 00:05:09,680 这个切换呢有一段进程切换的代码 131 00:05:09,720 --> 00:05:12,760 交替切换到最后然后再绕回来 132 00:05:12,800 --> 00:05:14,120 这时候我们看到 133 00:05:14,160 --> 00:05:15,600 物理的CPU上的指令指针 134 00:05:15,640 --> 00:05:17,680 它还是任何一个时刻 135 00:05:17,720 --> 00:05:19,200 只执行一条指令 136 00:05:19,240 --> 00:05:22,120 好这有一个执行的顺序 137 00:05:22,160 --> 00:05:23,600 那在操作系统管理下 138 00:05:23,640 --> 00:05:25,120 我们把这个切换代码 139 00:05:25,160 --> 00:05:27,840 作为一个独立的部分来看待 140 00:05:27,880 --> 00:05:29,040 我们可以观察 141 00:05:29,080 --> 00:05:31,560 各个进程内部它自己的执行状态 142 00:05:31,600 --> 00:05:33,640 好这时候呢我们就把 143 00:05:33,680 --> 00:05:35,120 一个CPU里头物理的指令指针 144 00:05:35,160 --> 00:05:40,160 转变成了四个并发执行的进程 145 00:05:40,200 --> 00:05:41,400 的指令指针 146 00:05:41,440 --> 00:05:44,080 A B C D 147 00:05:44,120 --> 00:05:45,360 应用程序在做的时候 148 00:05:45,400 --> 00:05:50,480 只观察你所关心的进程A B或者C D里头 149 00:05:50,520 --> 00:05:52,680 它的执行的情况 150 00:05:52,720 --> 00:05:55,800 那这是一个 啊 这是体现出四个 151 00:05:55,840 --> 00:05:57,560 好这种特征我们从时间轴上 152 00:05:57,600 --> 00:05:59,400 可以看到一种什么样的特征 153 00:05:59,440 --> 00:06:01,440 就是ABCD四个进程 154 00:06:01,480 --> 00:06:04,360 在时间轴上它们是交替运行的 155 00:06:04,400 --> 00:06:07,640 宏观上它是并发执行的 156 00:06:07,680 --> 00:06:09,160 好 有了这些讨论之后 157 00:06:09,200 --> 00:06:11,080 我们需要来强调一下 158 00:06:11,120 --> 00:06:13,600 进程和程序之间的联系 159 00:06:13,640 --> 00:06:15,760 和它们之间的区别 160 00:06:15,800 --> 00:06:17,600 它们之间的联系是什么呢 161 00:06:17,640 --> 00:06:19,440 进程是处于运行状态下的 162 00:06:19,480 --> 00:06:21,560 程序的抽象 163 00:06:21,600 --> 00:06:23,760 和程序是相关的 164 00:06:23,800 --> 00:06:25,640 好程序呢是一个静态的文件 165 00:06:25,680 --> 00:06:26,920 你比如说你的源代码 166 00:06:26,960 --> 00:06:28,520 或者说可执行文件 167 00:06:28,560 --> 00:06:31,880 而进程呢是执行中的程序 168 00:06:31,920 --> 00:06:35,040 除了程序之外它还有它的执行状态 169 00:06:35,080 --> 00:06:38,960 然后进程同一个程序的 170 00:06:39,000 --> 00:06:42,320 多次执行对应着不同的进程 171 00:06:42,360 --> 00:06:44,360 那我们不同的程序呢 172 00:06:44,400 --> 00:06:47,240 它的代码肯定是不一样的 173 00:06:47,280 --> 00:06:49,200 比如说在这里头我同一个命令 174 00:06:49,240 --> 00:06:53,400 IS多次执行它对应的是不同的进程 175 00:06:53,440 --> 00:06:58,080 那进程执行呢除了我们的程序之外 176 00:06:58,120 --> 00:06:59,920 还需要其它的一些资源 177 00:06:59,960 --> 00:07:03,080 比如说我们在这里头内存和CPU 178 00:07:03,120 --> 00:07:05,200 内存负责保存代码和数据 179 00:07:05,240 --> 00:07:07,640 CPU呢是用来执行指令的 180 00:07:07,680 --> 00:07:09,440 这是它们之间联系 181 00:07:09,480 --> 00:07:11,280 它们之间的区别呢 182 00:07:11,320 --> 00:07:14,720 我们刚才说了一静一动 183 00:07:14,760 --> 00:07:17,960 程序是有序代码的集合 184 00:07:18,000 --> 00:07:21,400 而进程呢是程序的执行 185 00:07:21,440 --> 00:07:24,280 它有用户态和内核态的切换 186 00:07:24,320 --> 00:07:28,080 然后进程是暂时的 187 00:07:28,120 --> 00:07:30,080 程序是永久的 188 00:07:30,120 --> 00:07:32,760 程序我可以放到一个文件系统里头 189 00:07:32,800 --> 00:07:34,480 那它就可以长期保存 190 00:07:34,520 --> 00:07:36,000 而进程呢它总是有一个开始 191 00:07:36,040 --> 00:07:36,520 一个结束 192 00:07:36,560 --> 00:07:37,680 一个变化的过程 193 00:07:37,720 --> 00:07:38,360 194 00:07:38,400 --> 00:07:38,960 这个结束了 195 00:07:39,000 --> 00:07:40,320 那这个进程也就不存在了 196 00:07:40,360 --> 00:07:42,880 197 00:07:42,920 --> 00:07:45,320 而进程和程序 198 00:07:45,360 --> 00:07:47,160 它们的组成呢是不一样的 199 00:07:47,200 --> 00:07:48,680 进程除了你的程序 200 00:07:48,720 --> 00:07:53,160 还包括数据和控制信息 201 00:07:53,200 --> 00:07:53,800 进程控制块 202 00:07:53,840 --> 00:07:54,920 203 00:07:54,960 --> 00:07:56,040 好 那到现在呢 204 00:07:56,080 --> 00:07:59,080 我们就对进程的大致的情况呢 205 00:07:59,120 --> 00:08:01,080 有一个基本的介绍 206 00:08:01,120 --> 00:08:01,360 207 00:08:01,400 --> 00:08:01,440