try ai
科普
编辑
分享
反馈
  • 操作系统内核:数字主权的核心原理

操作系统内核:数字主权的核心原理

SciencePedia玻尔百科
关键要点
  • 硬件强制的特权级别(内核模式 vs. 用户模式)是系统安全的基础,通过系统调用来仲裁对关键资源的访问。
  • 虚拟内存是由内核管理的一种强大幻象,它为每个应用程序提供私有地址空间,从而实现了按需分页和写时复制等功能。
  • 内核通过上下文切换来 juggling( juggling 有“同時處理、應付”的意思,此處意譯為“同時處理”)多个程序,其中机制(如何切换)与策略(何时切换)之间的区别对于实现系统目标至关重要。
  • 单体内核与微内核设计之间的架构选择,体现了在原始性能与可信计算基安全性之间的关键权衡。

引言

在我们数字设备的用户友好界面之下,隐藏着操作系统内核——这个无形的引擎编排着每一个动作。它是管理硬件资源、实施安全策略的主控制器,并创造出一种令人信服的幻象,让数百个程序似乎能在一台机器上同时运行。然而,对许多人来说,这个关键组件的内部工作原理仍然是一个黑匣子。本文将揭开抽象的层层面纱,揭示支配内核领域的核​​心原理。它旨在揭开计算机在最低软件层面的真实运作方式的神秘面纱,弥合用户应用程序与物理硬件之间的鸿沟。

旅程始于第一章​​原理与机制​​,该章探讨了内核世界的基本法则。我们将剖析用户模式和内核模式之间的严格分离、虚拟内存的优雅魔力、进程调度的艺术以及对硬件中断的精细处理。在这一基础上,第二章​​应用与跨学科联系​​将展示这些原理的实际应用。我们将追溯内核从计算机启动那一刻起获取权力的路径,审视其在现代云环境中作为守护者的角色,并发现其核心抽象如何催生了像现代网络浏览器这样复杂的技术。

原理与机制

如果你能剥开电脑的层层面纱,越过那些精致的窗口和多彩的图标,你会在其核心发现一个奇异而精彩的世界。这就是操作系统内核的领域。它并非普通意义上的程序;它是幕后的操纵者、最高的仲裁者,以及硬件的“嫉妒的”守护者。其主要工作是创造一系列强大且令人信服的幻象,让每个应用程序都相信自己独占了整台机器,而实际上,数百个程序正在争夺资源、时间和注意力。为实现这一宏大的“骗局”,内核依赖于少数几个深刻的原理和巧妙的机制,这些不仅仅是聪明的软件技巧,更是硬件与指挥它的代码之间的深度协作。

领地法则:特权与保护

现代内核的首要且最基本的原则是,它不能信任它所运行的程序。你的网络浏览器中的一个错误不应该能够导致整个系统崩溃或窥探你的密码管理器。这种分离不是君子协定;它是由处理器芯片本身强制执行的严格法律。

这种强制是通过​​特权级别​​实现的,通常称为​​环(rings)​​。在最基本的层面上,处理器至少在两种模式下运行:一种是为应用程序设定的高度受限的​​用户模式​​,另一种是为操作系统设定的拥有全部权限的​​内核模式​​(或称监督者模式)。把它想象成一个王国:应用程序是平民,而内核是君主。某些CPU指令被认为是“特权的”,如果平民试图使用它们,就会直接失败。

什么样的指令如此特殊?任何可能影响整个王国稳定或安全的东西。这包括修改计算机基本内存映射的指令,如加载新的全局描述符表(LGDTLGDTLGDT)或中断描述符表(LIDTLIDTLIDT);改变处理器核心操作模式的指令,如写入控制寄存器(CRxCRxCRx);或那些通过模型特定寄存器(MSRsMSRsMSRs)配置高级CPU功能的指令。如果一个用户程序可以执行这些指令,它就能瞬间成为国王,使所有保护措施都形同虚设。硬件确保这些操作专属于0环(Ring 0),即内核的专属领域。用户程序尝试执行此类指令不仅会失败,还会触发一个​​陷阱(trap)​​,这是一个硬件强制的“警报”,立即将控制权转移给内核。

那么,如果应用程序如此无力,它们如何执行像打开文件或通过网络发送数据这样明显需要硬件操作的基本任务呢?它们必须正式向君主请愿。这个正式的过程就是​​系统调用​​。系统调用是一条特殊指令,它充当一个受控的网关,一个从用户模式进入内核模式的暗门。应用程序将其请求——“我想从此文件中读取50个字节”——打包起来,并执行陷阱。处理器切换到内核模式,并开始执行一个特定的、受信任的内核例程。

但内核是一位明智而多疑的君主。它知道用户程序可能是恶意的,或者仅仅是有缺陷的。当用户程序传递信息时,比如一个指向它希望放置数据的内存缓冲区的指针,内核不能盲目信任该指针。如果这个指针不是指向应用程序的内存,而是指向内核自己的秘密代码呢?跟随它将是灾难性的。为防止这种情况,内核采用了一套严密的安全协议。它不直接使用用户的指针,而是使用像[copy_from_user](/sciencepedia/feynman/keyword/copy_from_user)和copy_to_user这样的特殊例程。这些例程在用户世界和内核的安全内部空间之间逐字节复制任何数据之前,会仔细验证内存范围是否属于用户进程。在用户-内核边界上的这种小心翼翼的舞蹈是系统安全与稳定性的基石。

塑造幻象:虚拟内存的魔力

也许内核创造的最优雅的幻象是​​虚拟内存​​。你电脑上运行的每个程序——你的文本编辑器、你的音乐播放器、一个命令提示符——都好像独占了计算机的全部内存,这些内存从地址零开始,以一个干净、私有、连续的块状布局呈现。当然,这完全是虚构的。实际上,物理内存(RAM)是属于几十个进程的数据的混乱混合体,所有数据都碎片化且散乱分布。

这个魔术是由一个名为​​内存管理单元(MMU)​​的硬件完成的,它充当一个实时翻译器。当程序试图访问一个“虚拟地址”时,MMU在内核的指导下,将其翻译成RAM中的一个物理地址。内核在称为​​页表​​的数据结构中维护着这个翻译的“字典”。

让这个系统真正卓越的是当翻译失败时会发生什么。这个事件,称为​​页错误(page fault)​​,不一定是一个错误。它是一个信号,是硬件暂停并对内核说:“我对这个地址感到困惑,你能帮忙吗?”的时刻。内核对这个问题的回应,使得许多现代特性成为可能。

  • ​​一个真正的错误:​​ 假设一个程序试图访问一个内核未分配给它的虚拟地址。MMU在页表中查找,找不到有效的翻译。它触发一个页错误。内核的页错误处理程序被唤醒,检查它自己的记录(进程的​​虚拟内存区域​​,或VMAs),并确定这次访问是非法的。然后它给出一个判决:一个段错误(SIGSEGV),通常会终止这个行为不端的程序。在这里,页错误是系统对无效操作的免疫反应。

  • ​​一次高效的延迟(按需分页):​​ 假设一个程序需要访问一个大文件中的一部分数据。在开始时就将整个文件加载到内存中是浪费的。相反,内核根本不加载它。当程序首次尝试访问那块内存时,MMU找不到映射并产生页错误。内核的处理程序检查该地址,意识到它是一个有效但“尚未存在”的页,便从容地将所需数据从磁盘加载到RAM的一个物理帧中,更新页表以完成映射,然后恢复程序。该应用程序完全不知道自己被暂停了;对它来说,内存似乎一直都在那里。这次页错误不是一个错误,而是一个触发即时加载的信号。

  • ​​一次聪明的优化(写时复制):​​ 当一个程序创建子进程时,子进程通常需要父进程内存的一个相同副本。立即制作一个完整的副本会很慢且浪费,特别是当子进程可能只读取内存或只改变其中一小部分时。所以,内核耍了一个花招。它给子进程的页表条目指向与父进程完全相同的物理页,但将它们全部标记为​​只读​​。只要两个进程都只读取数据,它们就愉快地共享同一块物理RAM。但当其中任何一个试图写入一个共享页时,MMU会执行只读规则并触发一个页错误。内核处理程序随后识别出这个特殊情况,一个​​写时复制(Copy-on-Write, CoW)​​错误。它迅速创建该单个页面的一个私有副本,更新出错进程的页表以指向新的、可写的副本,然后恢复它。这次页错误是一种机制,用以将昂贵的复制操作推迟到真正需要它的最后一刻。

杂耍的艺术:进程与时间

第二个伟大的幻象是并发执行。仅有少数几个CPU核心,如何能让几十个应用程序看似同时运行?内核是一个杂耍大师,它以惊人的速度在程序之间切换注意力——这个过程称为​​上下文切换​​。

“上下文”是一个正在运行的程序的精髓:它当前的思维状态。要暂停一个程序并恢复另一个,内核必须细致地保存旧程序的上下文并恢复新程序的上下文。这包括​​程序计数器(PC)​​,它知道下一条要执行的指令的地址;​​栈指针(SP)​​和​​帧指针(FP)​​,它们管理程序的临时暂存区;以及所有通用寄存器的内容。这个保存的状态是程序执行的一个完整快照。

其细节之精细令人咋舌。即使是一条机器指令也可能有必须被保留的内部状态。例如,某些架构有像rep movs这样复制大块内存的指令。这条指令是一个硬件循环,可能会在执行中途被中断。为了正确地恢复它,内核不仅必须保存指令的地址(PC),还必须保存跟踪其进度的寄存器——剩余计数、源地址和目标地址。恢复这些值使得指令能够精确地从它离开的地方继续执行,确保没有一个字节被遗漏或重复复制[@problemid:3670159]。

这就引出了操作系统设计中最优美的区别之一:​​机制与策略​​。

  • ​​机制​​是“如何做”。内核在硬件的帮助下,提供了上下文切换的机制和一个可以周期性中断CPU的计时器。这些是进行“杂耍”的原始工具。
  • ​​策略​​是“做什么”和“为什么做”。策略存在于内核中一个叫做​​调度器​​的部分,它决定何时切换以及切换到哪个程序。

相同的机制可以服务于截然不同的策略。考虑一个运行单一、关键控制循环的简单工业控制器。它的调度策略可能很简单:“永远运行主循环,除非它明确让出CPU。” 上下文切换机制存在,但策略很少使用它。现在考虑一个繁忙的大学服务器,有数百名学生在运行程序。目标是公平性和响应性。这里的调度策略是复杂的:它可能会使用计时器中断给每个用户一小片CPU时间(一个时间片),在他们之间快速切换,以确保没有人被饿死,并且交互式终端感觉灵敏。机制是相同的,但策略才是使系统目标得以实现的关键。

不速之客:处理中断

CPU之外的世界是异步且无序的。网卡收到一个数据包,你按下一个键,磁盘完成了数据读取。这些事件不能等待内核准备好;它们需要立即的关注。它们触发一个硬件​​中断​​,强制停止当前运行的代码,并将CPU转向内核中的一个​​中断处理程序​​。

在中断处理程序中运行就像在高速公路上被交警拦下:你必须快速处理情况,并且你处于一个高度受限的环境中。这被称为​​中断上下文​​或原子上下文。你不能做任何可能“睡眠”或阻塞的事情,因为整个系统(或至少一个CPU核心)实际上是暂停的,等待你完成。

这个约束带来了深刻而微妙的挑战。想象一下,处理器0上的一个内核线程获取了一个​​自旋锁​​(一种简单的锁)来保护一些共享数据。当它正处于关键工作的中途时,一个设备中断到达了同一个处理器0 tribulations 0。内核线程被抢占,中断处理程序开始运行。现在,如果那个处理程序需要访问完全相同的数据,并试图获取完全相同的锁呢?它会自旋,等待锁被释放。但是锁正被那个刚刚被处理程序中断的线程持有!线程无法运行以释放锁,因为处理程序正在运行。处理程序在获得锁之前无法完成。这是一个完美的、无法逃脱的​​死锁​​。处理器将永远旋转,完全冻结。

解决方案揭示了内核编程的一条黄金法则:当获取一个可能被中断处理程序使用的锁时,你必须首先禁用你CPU上的本地中断。这个简单的动作通过确保处理程序在你完成关键工作并释放锁之后才能运行,从而防止了死锁 scenario。

这个“禁止睡眠”的规则还有其他深远的影响。如果一个中断处理程序需要分配一小块内存缓冲区怎么办?一个通用的内存分配器是一个复杂的野兽;如果内存紧张,它可能需要睡眠,以便整理数据或等待一个页面被写入磁盘。从中断处理程序中调用这样的函数是非法的,会导致灾难。为了解决这个问题,内核使用复杂的策略:特殊的非阻塞分配器,从紧急预分配的池中获取内存,或者将大部分工作推迟到“下半部”机制(如工作队列)中,这个机制稍后会在一个安全的、可阻塞的进程上下文中运行[@problemid:3640045]。

架构师的困境:王国应该有多大?

我们已经看到了内核巨大的权力和责任。这引出了最后一个关键的架构问题:这些职责中,哪些必须位于特权内核内部,哪些可以委托给信任度较低的用户空间程序?答案定义了​​可信计算基(TCB)​​的边界——即为确保系统安全而必须正确无误的所有组件的集合。TCB中的一个单一缺陷就可能危及整个系统。

这个问题是两大内核架构之间伟大辩论的核心:

  • ​​单体内核:​​ 这是“大王国”方案。几乎所有的操作系统服务——文件系统、网络栈、设备驱动、内存管理——都被编译成一个庞大的、特权级的可执行文件。组件之间的通信就像一个简单的函数调用一样快。然而,TCB是巨大的。一个很少使用的音频驱动程序中的缺陷,可能被利用来接管整台机器。

  • ​​微内核:​​ 这是“小城堡”方案。内核的TCB被保持在人力所能及的最小范围内,只提供最基本的服务:调度、基本内存管理,以及一种​​进程间通信(IPC)​​机制。所有其他服务,如文件系统和驱动程序,都作为独立的、无特权的用户空间进程运行。

这不仅仅是哲学上的差异;这是一个我们可以用冷峻的概率逻辑来分析的权衡。让我们建立一个简单的模型。假设每行代码都有某个微小的、独立的概率β\betaβ包含一个危及安全的缺陷。那么TCB中缺陷的期望数量,即其“漏洞表面”,就是其代码行数乘以β\betaβ。

微内核显著地缩小了TCB。通过将kkk个服务(每个大小为sss)移出内核,它将TCB大小减少了ksksks。即使在为IPC机制增加了比如每个服务rrr行代码之后,新的TCB大小是(N−ks+kr)(N - ks + kr)(N−ks+kr),其中NNN是原始单体内核的大小。如果服务很大且IPC机制精简(s≫rs \gg rs≫r),那么缩减是巨大的。

对安全性的影响是指数级的。如果可利用缺陷的出现遵循一个均值为λ\lambdaλ(缺陷的期望数量)的泊松分布,那么TCB完美安全(0个缺陷)的概率是exp⁡(−λ)\exp(-\lambda)exp(−λ)。它含有至少一个可利用缺陷的概率是p=1−exp⁡(−λ)p = 1 - \exp(-\lambda)p=1−exp(−λ)。通过大幅减小TCB的大小,微内核使得λ\lambdaλ变得小得多,这反过来又使得系统被攻破的概率大大降低。这种优雅的数学关系表明,一种旨在最小化信任的架构选择,如何直接转化为可量化的安全性提升,将一种设计哲学变成了一种强大的风险管理原则。

应用与跨学科联系

在游历了操作系统内核错综复杂的原理和机制之后,我们可能会将其视为一台设计精美复杂的机器。但要真正欣赏其优雅之处,我们必须看到它运动时的样子。就像物理学中的任何宏大理论一样,内核的概念的最终意义不在于其抽象的设计,而在于它们如何塑造我们的世界。它们不仅仅是软件的蓝图;它们是整个数字生态系统的基本规则,从你口袋里的智能手机到驱动云的庞大服务器集群。

现在让我们来探索这个充满活力的领域,看看内核的保护、抽象和资源管理原则如何以令人惊讶和深刻的方式在技术和科学领域发挥作用。在这里,机器焕发生机。

内核的创生:从上电到主权在握

每次你按下电源按钮,都会启动一个非凡的序列,一个像王位继承一样精心编排的权力交接。计算机,这个仅仅是硅和金属的集合体,必须自力更生,为它的统治者——内核——加冕。但我们如何信任这个过程呢?在数字威胁的世界里,我们如何知道接管控制权的是合法的内核,而不是冒名顶替者?

答案在于一个被称为​​安全启动​​的美妙加密仪式。这个过程不是从代码开始,而是从信任开始——一个锚定在不可变硬件中的信任,即一个不可更改的启动只读存储器(ROM)。这个ROM包含一个主公钥,即系统的“信任根”。当机器上电时,这个首个受信任的组件被唤醒并充当守门人。它检查启动链中的下一个软件——引导加载程序(bootloader),它存储在像硬盘这样的可变介质上。它不仅仅是运行它;它首先根据受信任的公钥验证其数字签名。此外,为防止攻击者加载一个老旧、易受攻击的引导加载程序版本,它会对照一个特殊的、防篡改的​​单调计数器​​检查版本号,该计数器只能增加,不能减少。只有当签名有效且版本是最新的,ROM才会交出控制权。这个过程创建了一条​​信任链​​:受信任的ROM验证引导加载程序,而现在受信任的引导加载程序又依次验证下一个组件,如此下去,直到最后操作系统内核本身被验证并加载。内核的权威不是凭空获得的;它是通过每一步的加密验证赢得的。

其合法性确立后,机械的登基过程便开始了。在一个典型的x86系统中,处理器在一种称为“实模式”的原始状态下唤醒,模拟几十年前的祖先。它从一个固定的地址——复位向量——获取第一条指令,该向量指向固件(BIOS或UEFI)。固件初始化硬件并将控制权交给引导加载程序。现在,向现代过渡的精妙之舞开始了。引导加载程序必须将处理器从受限的实模式转换到强大的“保护模式”,这是一个多步骤的仪式,涉及创建全局描述符表(GDTGDTGDT)来定义内存段。一旦进入保护模式,它会执行另一个关键设置:构建页表以启用虚拟内存,并将其地址加载到一个特殊寄存器CR3CR3CR3中。最后,通过在CR0CR0CR0寄存器中设置一个位,它启用了分页。在这一刻,虚拟内存的抽象世界应运而生。舞台完全搭好后,引导加载程序执行其最后一幕:它跳转到内核的入口点,君主登基。

内核:终极守护者

登基之后,内核的首要且最庄严的职责是维持秩序。它是终极守护者,负责在其统治下运行的无数程序之间创建和维护边界。这是保护原则最具体的形式。

考虑一下现代云环境,成千上万来自不同租户的应用程序运行在相同的物理硬件上。这怎么会不会乱成一团?内核提供了答案,但提供了不同强度的隔离。当我们在​​容器​​中运行应用程序时,它们就像一座大型公寓楼里的住户。它们共享相同的基础和管道——一个单一的主机内核。内核使用命名空间和控制组等机制为每个容器提供系统的私有视图,但共享内核中的一个根本性漏洞可能会危及整栋大楼。这是一个强大的边界,但不是最强的。

对于有更严格安全要求的应用程序,内核可以通过虚拟机监控程序(hypervisor)提供​​虚拟机(VMs)​​。虚拟机不是公寓;它是一座独立的房子,拥有自己的地基:它自己的客户机内核。一个虚拟机的内核被攻破不会影响其邻居,因为它们不共享内核。容器和虚拟机之间的选择,是根据工作负载声明的安全需求来匹配隔离边界强度的一个漂亮应用,这是系统设计的核心原则。

内核作为守护者的角色不仅仅是建造静态的墙壁;它关乎管理活动的流动。在现代系统中,内核甚至学会了授权。为了提高性能和鲁棒性,许多设备驱动程序——与硬件对话的软件——正被移出内核,进入用户空间。这似乎有风险;你如何防止一个有缺陷的用户模式驱动程序使系统崩溃或读取另一个进程的内存?内核扮演着“管理者的管理者”的角色。它将设备协议的复杂逻辑委托给用户空间驱动程序,但保留对硬件特权能力的严格、不可委托的控制。通过使用一个称为输入-输出内存管理单元(IOMMU)的硬件,内核对硬件进行编程,以确保设备的直接内存访问(DMA)仅限于其自身驱动程序进程的内存。内核守护着权力的终极杠杆,在保证安全的同时实现了灵活性和性能。

幻象的艺术:为程序创造世界

除了作为守护者,内核还是一位幻象大师。它为每个程序创造一个定制的宇宙,一个由虚拟内存这一强大抽象构建起来的干净、私有、可预测的世界。程序相信自己独占了机器的全部内存,一个从地址零向上延伸的无缝空间。

这个幻象是如此强大,以至于内核甚至可以邀请他人参与其创造。考虑Linux中的userfaultfd机制。一个程序可以请求内核:“如果任何线程尝试访问这片内存区域并且页面不存在,不要自己处理。只需暂停该线程并通知我。”当页错误发生时,内核正是这么做的。它向一个用户空间处理程序进程发送消息,该进程随后可以决定为该页面提供什么数据。这种合作的魔力实现了令人难以置信的壮举,比如跨大陆实时迁移虚拟机。一个虚拟机可以在一台没有内存的新机器上启动,当它对页面产生缺页中断时,处理程序可以通过网络从其原始位置获取它们,从而无缝地动态重构其状态。内核和用户空间在一个优美的舞蹈中协同工作,以维持这一宏伟的幻象。

也许对内核抽象力量最令人惊叹的证明是现代网络浏览器。内核提供了一套基本的构建块:进程、线程、虚拟内存、文件和网络。在此基础上,浏览器构建了另一个更高级别的操作系统——一个“Web操作系统”。在这个世界里,Web源(origin)是主体,渲染器进程是“进程”。同源策略是访问控制模型。JavaScript事件循环是一种协作式调度。IndexedDB和缓存存储充当按源划分的文件系统。Service Workers就像守护进程或后台服务。浏览器重新实现了每一个核心的操作系统角色,但这一切都建立在内核的肩膀上,是下面的巨人使得整个结构成为可能。

追求性能:效率的无形之舞

一个有效的统治者不仅必须强大和公正,还必须优雅和高效。内核处于一场永恒的舞蹈中,平衡着控制的需求与性能的要求。每一层抽象和每一次安全检查都带有潜在的成本。

有时候,要做到快,最优雅的方式是优雅地让开。这就是像​​futex​​(快速用户空间互斥锁)这样的同步原语背后的哲学。当多个线程需要协调对共享数据的访问时,天真的方法是每次加锁和解锁操作都让内核介入。这是安全的,但切换到内核模式的开销很高。futex允许线程在常见的、无竞争的情况下完全在用户空间管理锁。一个线程可以用一条原子指令来获取锁。只有当出现真正的冲突时——一个线程试图获取一个已被另一个线程持有的锁——它才会进行系统调用。内核然后介入,将等待的线程置于睡眠状态。这是一个优美的设计,它只在绝对必要时才利用内核作为调度器的能力,从而在快速路径上实现了近乎零的开销。

在计算的前沿,性能正在被重新定义。在“无服务器”或“函数即服务”(FaaS)的世界里,性能意味着近乎瞬时的启动。梦想是为每一次函数调用都提供其自己完全隔离的执行环境,但启动一个传统的虚拟机可能需要数秒钟——在这个领域里是永恒的时间。解决方案是内核极简主义的杰作。通过创建一个​​微型虚拟机(microVM)​​——一个拥有经过激进精简的客户机内核和最基本虚拟设备(例如,一个网卡和一个块设备)的虚拟机——启动过程被大大缩短。结合快照/恢复技术,即加载一个预先启动的客户机内存镜像,启动时间可以从秒级缩减到毫秒级。这提供了虚拟机的强大、硬件强制的隔离性,同时具备容器的敏捷性,从而催生了一种新的安全、按需计算范式。

内核的谦卑:当统治者成为仆人

我们的旅程将内核描绘成信任的最终仲裁者,安全的基础层。我们以一个最后的、优美的悖论结束:当安全原则如此强大,以至于它们被反过来用于内核本身时,会发生什么?

在要求最苛刻的安全环境中,我们必须考虑到即使是操作系统内核也可能被攻破的可能性。这导致了对传统信任模型的惊人颠覆,这得益于诸如英特尔的软件防护扩展(SGX)和ARM的TrustZone等硬件特性。这些​​可信执行环境(TEEs)​​在处理器内部创建了一个硬件强制隔离的“飞地”(enclave)或“安全世界”。这个飞地内的代码和数据是机密的、防篡改的,即使是运行在最高特权级别的主机操作系统内核也无法访问。

在这种模型中,内核的角色发生了反转。如果我们将一个关键的密钥库放在TEE内部,内核将无法直接访问它。要执行加密操作,内核必须谦卑地向飞地请求服务。全能的内核变成了​​不受信任的主机​​,一个仆人,其工作是为飞地管理资源,但被禁止窥探其内部。这不是内核的失败,而是其自身原则的终极胜利。隔离和最小权限的理念是如此根本,以至于它们可以用来治理统治者本身,为我们的数字世界创造一个更安全的基础。