操作系统如何运行的?
原文标题:When Does Your OS Run?
原文链接:https://manybutfinite.com/post/when-does-your-os-run/
原文发布时间:Oct 28th, 2014
这有个问题:在你读到这一段话的时候,你的 OS 在运行吗?或者只是你的浏览器在运行?或者它们可能都在空闲状态,只是等你来点什么?
这个问题很简单,但却贯穿了软件的运行本质。为了准确回答这些问题,我们需要一个良好的操作系统行为心理模型,这反过来会影响性能、安全性和故障排除决策。我们将在本系列文章中使用 Linux 作为主要的操作系统(OS X 和 Windows 客串)来构建的模型。我会想深入研究的读者提供 Linux 内核源代码的链接。
这里的基本都原理是在任何给定时刻,CPU 上只有一个进程处于活动状态。任务通常是一个程序,比如浏览器或者音乐播放器,也可以是操作系统线程,但就一个任务。不是两个或者更多的任务。也永远不是 0 个任务。永远都是一个任务。
这听起来是问题的。比如说,如果你的音乐播放器占用了 CPU,不让其他任务运行怎么办?你无法打开一个工具来杀死它,甚至鼠标点击也是徒劳的,因为 OS 无法处理。它可能会不停地卡在“What does the fox say?”这里,引起办公室的一场骚乱。
这时就需要中断了。就像神经系统会中断大脑来引入外部刺激——一声巨响、触碰肩膀——计算机主板上的芯片组会中断 CPU 以传递外部事件的消息——按键盘、网络数据包到达、磁盘完成读取等。硬件外设、主板上的中断控制器和 CPU 它自己这几个一起协作来实现这些中断(interrupts)。
为了追踪最重要的东西——时间,中断也是必不可少的。在启动的过程中,内核会启动硬件定时器来让它定时发送定时器中断,比如说每 10 微秒发送一次。每次定时结束时,CPU 给内核有机会让它更新系统数据并评估当前状况:当前程序是否运行太久了?是否有 TCP 超时?中断让内核有机会思考这些问题,并采取适当的行动。就像你在一天中设置周期性的闹钟,每次闹钟响了就检查:我应该做我现在在做的事情吗?还有更紧急的事情吗?有一天你发现 10 年过去了。
内核把 CPU 这种周期性的劫持叫做时钟(ticks),所以中断实际上让你的 OS 跳动。不过还有:中断也用来处理一些软件事件,比如说整数溢出和页面异常,这些都不涉及到外部的硬件。中断是进入操作系统内核最频繁的和最关键的入口点。它们并不是 EE 人员需要担心的什么奇怪东西,这只是你的操作系统运行的机制。
说得够多了,我们实际看看吧。下面是 Intel Core i5 系列的网卡的中断。这个图是可以点击的,链接到具体的页面。
先看看这个。首先,由于中断的来源很多,如果硬件只是简单地告诉 CPU“嘿,发生了一些事情!”,这样没有什么帮助。悬念会让人难以忍受。因此在计算机通电之后,每个设备都分配了一个中断请求线(interrupt request line, IRQ)。这些 IRQ 依次由中断控制器映射为中断向量(interrupt vector),一个介于 0 和 255 之间的数字。当一个中断到达 CPU 时,它已经有了一个很好的、定义良好的数字,与不可预测的硬件隔离开。
CPU 有一个指针,指向由内核提供的 255 个函数组成的数组,其中每个函数都是特定中断向量的处理程序。稍后我们会更详细地介绍这个数组,即中断描述符表(Interrupt Descriptor Table, IDT)。
每当中断到达时,CPU 将其向量用作 IDT 的索引,并运行适当的处理程序。这是在当前运行的任务上下文中发生的特殊函数调用,允许操作系统以最小的开销快速响应外部事件。因此,网络服务器在向你发送数据时,会间接调用你 CPU 中的一个函数,这既酷又可怕。下面给出了一种情况,在中断到达时,CPU 正在忙于运行 Vim 命令:
请注意中断的到达是如何导致切换到核心态和零环权限的,但这并不改变活动进程。这就好像 Vim 直接对内核进行了一个魔术函数调用,但 Vim 仍然在那里,其地址空间完好无损,等待该调用返回。
令人兴奋的东西!唉,我需要保持这个 post-sized,所以让我们现在完成。我知道我们还没有回答开始的问题,实际上还提出了新的问题,但你现在怀疑,当你读这句话时,蜱虫正在发生。我们会在充实我们的动态操作系统行为模型时找到答案,浏览器场景也会变得清晰。如果你有问题,特别是在帖子发布的时候,尽管提出来,我会在帖子中或评论中回答它们。下一期将于明天在 RSS 和 Twitter 上播出。(这句是机翻)