03-内核的职责
内核的职责
内核所能执行的主要任务如下所示。
- 进程调度:计算机内均配备有一个或多个CPU(中央处理单元),以执行程序指令。与其他UNIX系统一样,Linux属于抢占式多任务操作系统。“多任务”意指多个进程(即运行中的程序)可同时驻留于内存,且每个进程都能获得对CPU的使用权。“抢占”则是指一组规则。这组规则控制着哪些进程获得对CPU的使用,以及每个进程能使用多长时间,这两者都由内核进程调度程序(而非进程本身)决定。
- 内存管理:以一二十年前的标准来看,如今计算机的内存容量可谓相当可观,但软件的规模也保持了相应地增长,故而物理内存(RAM)仍然属于有限资源,内核必须以公平、高效地方式在进程间共享这一资源。与大多数现代操作系统一样,Linux也采用了虚拟内存管理机制(6.4节),这项技术主要具有以下两方面的优势。
- 进程与进程之间、进程与内核之间彼此隔离,因此一个进程无法读取或修改内核或其他进程的内存内容。
- 只需将进程的一部分保持在内存中,这不但降低了每个进程对内存的需求量,而且还能在RAM中同时加载更多的进程。这也大幅提升了如下事件的发生概率,在任一时刻,CPU都有至少一个进程可以执行,从而使得对CPU资源的利用更加充分。
- 提供了文件系统:内核在磁盘之上提供有文件系统,允许对文件执行创建、获取、更新以及删除等操作。
- 创建和终止进程:内核可将新程序载入内存,为其提供运行所需的资源(比如,CPU、内存以及对文件的访问等)。这样一个运行中的程序我们称之为“进程”。一旦进程执行完毕,内核还要确保释放其占用资源,以供后续程序重新使用。
- 对设备的访问:计算机外接设备(鼠标、键盘、磁盘和磁带驱动器等)可实现计算机与外部世界的通信,这一通信机制包括输入、输出或是两者兼而有之。内核既为程序访问设备提供了简化版的标准接口,同时还要仲裁多个进程对每一个设备的访问。
- 联网:内核以用户进程的名义收发网络消息(数据包)。该任务包括将网络数据包路由至目标系统。
- 提供系统调用应用编程接口(API):进程可利用内核入口点(也称为系统调用)请求内核去执行各种任务。Linux系统调用API是本书的主题。3.1节会详细描述进程在执行系统调用时所经历的步骤。
除了上述特性外,一般而言,诸如Linux之类的多用户操作系统会为每个用户营造一种抽象:虚拟私有计算机(virtual private computer)。这就是说,每个用户都可以登录进入系统,独立操作,而与其他用户大致无干。例如,每个用户都有属于自己的磁盘存储空间(主目录)。再者,用户能够运行程序,而每一程序都能从CPU资源中“分得一杯羹”,运转于自有的虚拟地址空间中。而且这些程序还能独立访问设备,并通过网络传递信息。内核负责解决(多进程)访问硬件资源时可能引发的冲突,用户和进程对此则往往一无所知。
内核态和用户态
现代处理器架构一般允许CPU至少在两种不同状态下运行,即:用户态和核心态(有时也称之为监管态supervisor mode)。执行硬件指令可使CPU在两种状态间来回切换。与之对应,可将虚拟内存区域划分(标记)为用户空间部分或内核空间部分。在用户态下运行时,CPU只能访问被标记为用户空间的内存,试图访问属于内核空间的内存会引发硬件异常。当运行于核心态时,CPU既能访问用户空间内存,也能访问内核空间内存。
仅当处理器在核心态运行时,才能执行某些特定操作。这样的例子包括:执行宕机(halt)指令去关闭系统,访问内存管理硬件,以及设备I/O操作的初始化等。实现者们利用这一硬件设计,将操作系统置于内核空间。这确保了用户进程既不能访问内核指令和数据结构,也无法执行不利于系统运行的操作。
以进程及内核视角检视系统
在完成诸多日常编程任务时,程序员们习惯于以面向进程(process-oriented)的思维方式来考虑编程问题。然而,在研究本书后续所涵盖的各种主题时,读者有必要转换视角,站在内核的角度上来看问题。为突显二者间的差异,本书接下来会分别从进程和内核视角来检视系统。
一个运行系统通常会有多个进程并行其中。对进程来说,许多事件的发生都无法预期。执行中的进程不清楚自己对CPU的占用何时“到期”,系统随之又会调度哪个进程来使用CPU(以及以何种顺序来调度),也不知道自己何时会再次获得对CPU的使用。信号的传递和进程间通信事件的触发由内核统一协调,对进程而言,随时可能发生。诸如此类,进程都一无所知。进程不清楚自己在RAM中的位置。或者换种更通用的说法,进程内存空间的某块特定部分如今到底是驻留在内存中还是被保存在交换空间(磁盘空间中的保留区域,作为计算机RAM的补充)里,进程本身并不知晓。与之类似,进程也闹不清自己所访问的文件“居于”磁盘驱动器的何处,只是通过名称来引用文件而已。进程的运作方式堪称“与世隔绝”——进程间彼此不能直接通信。进程本身无法创建出新进程,哪怕“自行了断”都不行。最后还有一点,进程也不能与计算机外接的输入输出设备直接通信。
相形之下,内核则是运行系统的中枢所在,对于系统的一切无所不知、无所不能,为系统上所有进程的运行提供便利。由哪个进程来接掌对 CPU 的使用,何时“接任”,“任期”多久,都由内核说了算。在内核维护的数据结构中,包含了与所有正在运行的进程有关的信息。随着进程的创建、状态发生变化或者终结,内核会及时更新这些数据结构。内核所维护的底层数据结构可将程序使用的文件名转换为磁盘的物理位置。此外,每个进程的虚拟内存与计算机物理内存及磁盘交换区之间的映射关系,也在内核维护的数据结构之列。进程间的所有通信都要通过内核提供的通信机制来完成。响应进程发出的请求,内核会创建新的进程,终结现有进程。最后,由内核(特别是设备驱动程序)来执行与输入/输出设备之间的所有直接通信,按需与用户进程交互信息。
本书后续内容中会出现如下措辞,例如:“某进程可创建另一个进程”、“某进程可创建管道”、“某进程可将数据写入文件”,以及“调用exit()以终止某进程”。请务必牢记,以上所有动作都是由内核来居中“调停”,上面的说法不过是“某进程可以请求内核创建另一个进程”的缩略语,以此类推。
进阶阅读
涵盖操作系统概念和设计,尤其是对 UNIX 操作系统加以重点关注的现代教科书包括:[Tanenbaum, 2007]、[Tanenbaum & Woodhull,2006]以及[Vahalia, 1996],最后一本包含了与虚拟内存架构有关的详细内容。[Goodheart & Cox, 1994]详细介绍了System V Release 4。[Maxwell, 1999]则是有选择性地针对 Linux 2.2.5 的部分内核源码进行了注释。[Lions, 1996]对第六版UNIX源码进行了详尽阐释,并一直是研究UNIX操作系统内幕的入门级经典。[Bovet & Cesati, 2005]描述了Linux2.6内核的实现。