<audio id="audio" title="03 | 你可以把Linux内核当成一家软件外包公司的老板" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/50/9a/50def8552f29579af4fe4dd67af1a39a.mp3"></audio>

在平时的生活中，我们几乎时时刻刻都在使用操作系统，只是大部分时间你都意识不到它的存在。比如你买了一部手机或者一台平板电脑，立马就能上手使用，这是因为它们里面都预先安装了操作系统。

所以啊，哪有什么岁月静好，只不过有人替你负重前行。而操作系统就扮演了这样一个负重前行的角色。那操作系统到底在背后默默地做了哪些事情，才能让我们轻松地使用这些电子设备呢？要想回答这个问题，我们需要把眼光放回到自己攒电脑的那个时代。

## 电脑组装好就能直接用吗？

那时候买电脑，经常是这样一个情景：三五个哥们儿一起来到电脑城，呼啦呼啦采购了一大堆硬件，有密密麻麻都是针脚的**CPU**；有铺满各种复杂电路的一块板子，也就是**主板**；还需要买块**显卡**，用来连接显示器；还需要买个**网卡**，里面可以插网线；还要买块**硬盘**，将来用来存放文件；然后还需要一大堆**线**，将这些设备和主板连接起来；最终再来一个**鼠标**，一个**键盘**，还有一个**显示器**。设备差不多啦，准备开整！

<img src="https://static001.geekbang.org/resource/image/ed/45/ed03667738a92d66626914fe5dc78d45.png" alt="">

好不容易组装完这一大堆硬件，还是不能直接用，你还需要安装一个操作系统。安装操作系统也是一件非常复杂的事，一点儿也不亚于把刚才那堆东西组装起来。这个安装过程可能会涉及十几个步骤、几十项配置。每一步骤配置完了，点击下一步，会出现个进度条。伴随着一堆难以理解的描述，最终安装步骤到达百分之百，才出现你熟悉的那个界面。

我这么说起来好像很容易，但是要把这事儿讲清楚估计得用一个专栏。这个复杂程度，咱们父母估计是上不了手了。所以，那个时候，能把这套东西都组装起来，是一件很拉风的事情。很多IT男甚至因为这项绝技“泡”到了妹子。

当操作系统安装完毕的时候，我妈通常会要求我一定要装一个QQ。看到妈妈在你装好的操作系统前愉快地和她的朋友聊天，这时候，经历过以上过程的你，多少应该能感受到操作系统的厉害了。

**操作系统究竟是如何把这么多套复杂的东西管理起来，从而弄出来一个简单到父母都会用的东西呢？**

很多事情就怕细想。不知道你有没有产生过这些疑问：

<li>
桌面上的图标到底是啥？凭啥我在鼠标上一双击，就会出来一个美丽的画面？这都是从哪里跑出来的？
</li>
<li>
凭什么我在键盘上噼里啪啦地敲，某个位置就会显示我想要的那些字符？
</li>
<li>
电脑怎么知道我鼠标点击的是这个地方，又是怎么知道我要输入的是这个地方？
</li>
<li>
我在键盘上点“a”，是谁在显示器上画出“a”这个图像呢？
</li>
<li>
为什么我一回车，这些字符就发到遥远的另外一台机器上去了？
</li>

对于普通用户来讲，其实只要会用就行了，但是咱们作为专业人士，要深入探究一下背后的答案。你别小看“双击鼠标打开聊天软件”这样一个简单的操作，它几乎涵盖了操作系统的所有功能。我们就从这个熟悉的操作，来认识陌生的操作系统。

操作系统其实就像一个软件外包公司，其内核就相当于这家外包公司的老板。所以接下来的整个课程中，请你将自己的角色切换成这家软件外包公司的老板，设身处地地去理解操作系统是如何协调各种资源，帮客户做成事情的。

想要学好咱们这门课，你要牢牢记住这段话，把这个概念牢牢扎根在心里，我之后的讲解都会基于此，帮你理解、记忆那些难搞的概念和原理。

同时，为了防止你混淆，我这里先强调一下。今后我所说的“用户”，都是指操作系统的用户，“客户”则是指外包公司的客户，这两者是对应的。

## “双击QQ”这个过程，都需要用到哪些硬件？

好，现在用户开始对着屏幕上的QQ图标双击鼠标了。

**鼠标和键盘**是计算机的**输入设备**。大部分的普通用户想要告诉计算机应该做什么，都是通过这两个设备。例如，用户移动了一下鼠标，鼠标就会通过鼠标线给电脑发消息，告知电脑，鼠标向某个方向移动了多少距离。

如果是一家外包公司，怎么才能知道客户的需求呢？你需要配备销售、售前等角色，专门负责和客户对接，把客户需求拿回来，我们把这些人统称为**客户对接员**。你可以跟客户说，有什么事儿都找对接员。

屏幕，也就是**显示器**，是计算机的**输出设备**，将计算机处理用户请求后的结果展现给客户，要不然用户无法知道自己的请求是不是到达并且执行了。

显示器上面显示的东西是由**显卡**控制的。无论是显示器还是显卡，这里都有个“坐标”的概念，也就是说，什么图像在哪个坐标，都是定义好了才画上去的。本来在某个坐标画了一个鼠标箭头，当接到鼠标移动的事件之后，你应该按相同的方向，按照一定的比例（鼠标灵敏度），在屏幕的某个坐标再画一个鼠标箭头。

作为外包公司，当客户给你提了需求，不管你做还是不做，最终做成什么样，你都需要给客户反馈，所以你要配备交付人员，将做好的需求展示给他们看。

在操作系统中，**输入设备驱动**其实就是**客户对接员**。有时候新插上一个鼠标的时候，会弹出一个通知你安装驱动，这就是操作系统这家外包公司给你配备对接人员呢。当客户告诉对接员需求的时候，对于操作系统来讲，输入设备会发送一个中断。这个概念很好理解。客户肯定希望外包公司把正在做的事情都停下来服务它。所以，这个时候客户发送的需求就被称为**中断事件**（Interrupt Event）。

显卡会有**显卡驱动**，在操作系统中称为**输出设备驱动**，也就是上面说的**交付人员**。

## 从点击QQ图标，看操作系统全貌

有了**客户对接员**和**交付人员**，外包公司就可以处理用户“在桌面上点击QQ图标”的事件了。

首先，鼠标双击会触发一个中断，这相当于客户告知客户对接员“有了新需求，需要处理一下”。你会事先把处理这种问题的方法教给客户对接员。在操作系统里面就是调用中断处理函数。操作系统发现双击的是一个图标，就明白了用户的原始诉求，准备运行QQ和别人聊天。

你会发现，运行QQ是一件大事，因为将来的一段时间，用户要一直和QQ进行交互。这就相当于你们公司接了一个大单，而不是处理零星的客户需求，这个时候应该单独立项。一旦立了项，以后与这个项目有关的事情，都由这个项目组来处理。

立项可不能随便立，一定要有一个**项目执行计划书**，说明这个项目打算怎么做，一步一步如何执行，遇到什么情况应该怎么办等等。换句话说，对QQ这个程序来说，它能做哪些事情，每件事情怎么做，先做啥后做啥，都已经作为程序逻辑写在程序里面，并且编译成为二进制了。这个程序就相当于项目执行计划书。

电脑上的程序有很多，什么有道云笔记的程序、Word程序等等，它们都以二进制文件的形式保存在硬盘上。硬盘是个物理设备，要按照规定格式化成为文件系统，才能存放这些程序。文件系统需要一个系统进行统一管理，称为**文件管理子系统**（File Management Subsystem）。

对于你们公司，项目立得多了，项目执行计划书也会很多，同样需要有个统一保存文件的档案库，而且需要有序地管理起来。

当你从资料库里面拿到这个项目执行计划书，接下来就需要开始执行这个项目了。项目执行计划书是静态的，项目的执行是动态的。

同理，当操作系统拿到QQ的二进制执行文件的时候，就可以运行这个文件了。QQ的二进制文件是静态的，称为**程序**（Program），而运行起来的QQ，是不断进行的，称为**进程**（Process）。

说了这么多，怎样才能立项呢？你会发现，一个项目要想顺畅进行，需要用到公司的各种资源，比如说盖个公章、开个证明、申请个会议室、打印个材料等等。这里有个两难的权衡，一方面，资源毕竟是有限的，甚至是涉及机密的，不能由项目组滥取滥用；另一方面，就是效率，咱是一个私营企业，保证项目申请资源的时候只跑一次，这样才能比较高效。

为了平衡这一点，一方面涉及核心权限的资源，还是应该被公司严格把控，审批了才能用；另外一方面，为了提高效率，最好有个统一的办事大厅，明文列出提供哪些服务，谁需要可以来申请，然后就会有回应。

在操作系统中，也有同样的问题，例如多个进程都要往打印机上打印文件，如果随便乱打印进程，就会出现同样一张纸，第一行是A进程输出的文字，第二行是B进程输出的文字，全乱套了。所以，打印机的直接操作是放在操作系统内核里面的，进程不能随便操作。但是操作系统也提供一个办事大厅，也就是**系统调用**（System Call）。

系统调用也能列出来提供哪些接口可以调用，进程有需要的时候就可以去调用。这其中，立项是办事大厅提供的关键服务之一。同样，任何一个程序要想运行起来，就需要调用系统调用，创建进程。

一旦项目正式立项，就要开始执行，就要成立项目组，将开发人员分配到这个项目组，按照项目执行计划书一步一步执行。为了管理这个项目，我们还需要一个项目经理、一套项目管理流程、一个项目管理系统，例如程序员比较熟悉的Jira。如果项目多，可能一个开发人员需要同时执行多个项目，这就要考验项目经理的调度能力了。

在操作系统中，进程的执行也需要分配CPU进行执行，也就是按照程序里面的二进制代码一行一行地执行。于是，为了管理进程，我们还需要一个**进程管理子系统**（Process Management Subsystem）。如果运行的进程很多，则一个CPU会并发运行多个进程，也就需要CPU的调度能力了。

每个项目都有自己的私密资料，这些资料不能被其他项目组看到。这些资料主要是项目在执行的过程中，产生的很多中间成果，例如架构图、流程图。

执行过程中，难免要在白板上或者本子上写写画画，如果不同项目的办公空间不隔离，一方面，项目的私密性不能得到保证，A项目的细节，B项目也能看到；另一方面，项目之间会相互干扰，A项目组的人刚在白板上画了一个架构图，出去上个厕所，结果B项目组的人就给擦了。

如果把不同的项目组分配到不同的会议室，就解决了这个问题。当然会议室是有限的，需要有人管理和分配，并且需要一个**会议室管理系统**。

在操作系统中，不同的进程有不同的内存空间，但是整个电脑内存就这么点儿，所以需要统一的管理和分配，这就需要**内存管理子系统**（Memory Management Subsystem）。

如果想直观地了解QQ如何使用CPU和内存，可以打开任务管理器，你就能看到QQ这个进程耗费的CPU和内存。

项目执行的时候，有了一定的成果，就要给客户演示。例如客户说要做个应用，我们做出来了要给客户看看，如果客户说哪里需要改，可以根据客户的需求再改，这就需要交付人员了。

QQ启动之后，有一部分代码会在显示器上画一个对话框，并且将键盘的焦点放在了输入框里面。CPU根据这些指令，就会告知显卡驱动程序，将这个对话框画出来。

于是使用QQ的用户就会很开心地发现，他能和别人开始聊天了。

当用户通过键盘噼里啪啦打字的时候，键盘也是输入设备，也会触发中断，通知相应的输入设备驱动程序。

我们假设用户输入了一个“a”。这就像客户提出了新的需求给客户对接员。客户对接员收到需求后，因为是对接这个项目的，所以就回来报告，客户提新需求了，项目组需要处理一下。项目执行计划书里面一般都会有当遇到何种需求应该怎么做的规定，项目组就按这个规定做了，然后让交付人员再去客户那里演示就行了。

对于QQ来讲，由于键盘闪啊闪的焦点在QQ这个对话框上，因而操作系统知道，这个事件是给这个进程的。QQ的代码里面肯定有遇到这种事件如何处理的代码，就会执行。一般是记录下客户的输入，并且告知显卡驱动程序，在那个地方画一个“a”。显卡画完了，客户看到了，就觉得自己的输入成功了。

当用户输入完毕之后，回车一下，还是会通过键盘驱动程序告诉操作系统，操作系统还是会找到QQ，QQ会将用户的输入发送到网络上。QQ进程是不能直接发送网络包的，需要调用系统调用，内核使用网卡驱动程序进行发送。

这就像客户对接员接到一个需求，但是这个需求需要和其他公司沟通，这就需要依靠公司的对外合作部，对外合作部在办事大厅有专门的窗口，非常方便。

<img src="https://static001.geekbang.org/resource/image/e1/4a/e15954f1371a4c782f028202dce1f84a.jpeg" alt="">

## 总结时刻

到这里，一个外包公司大部分的职能部门都凑齐了。你可以对应着下图的操作系统内核体系结构，回顾一下它们是如何组成一家公司的。

QQ的运行过程，只是一个简单的比喻。在后面的章节中，我会展开讲述每个部分是怎么工作的，最后我会再将这个过程串起来，这样你就能了解操作系统的全貌了。

<img src="https://static001.geekbang.org/resource/image/21/f5/21a9afd64b05cf1ffc87b74515d1d4f5.jpeg" alt="">

## 课堂练习

学习Linux，看代码是必须的。你可以找到最新版本的Linux代码，在里面找找，这几个子系统的代码都在哪里。

欢迎留言和我分享你的思考和疑问，也欢迎你把今天的内容分享给你的朋友，和他一起学习、进步。

<img src="https://static001.geekbang.org/resource/image/8c/37/8c0a95fa07a8b9a1abfd394479bdd637.jpg" alt="">
