引言

操作系统
图 1.1:三个常见的操作系统

作为大学生,每个人似乎都随身携带着一个笔记本电脑。以上这张图片是三个常见的操作系统:Windows、macOS 和 Linux。它们看起来很不一样,但实际上都属于操作系统(Operating System, OS)这个范畴。这门课旨在让你理解操作系统的核心概念、服务和设计原则,并通过一些典型的体系结构来展示它们是如何实现这些目标的。

操作系统导论通常要先回答三个问题:OS 为什么处在计算系统的核心位置,它到底负责哪些服务,以及为什么会发展出不同的系统结构。整门课的第一步,不是背术语,而是先把 OS 视为系统里负责协调资源、隔离硬件细节、并向上层提供抽象的一层核心软件。

计算环境的演化

理解 OS 的位置,可以先从计算环境的演化看起。

  • 1946 年以后,计算机从最早的通用计算设备发展起来。
  • 1960 年代进入高性能计算(High Performance Computing)和互联网(Internet)之前的阶段。
  • 1980 年代个人计算机(Personal Computer)普及。
  • 1990 年代互联网服务成为主流,计算机开始被当成网络基础设施。
  • 2010 年前后,计算进入智能终端、传感与普适连接(omnipresent connectivity and sensing)阶段。
  • 到 2020 年以后,人工智能与物联网进一步融合,形成 AIoT 之类的计算形态。

在这条线上,OS 一直是核心层。设备形态变了,OS 的角色也在变,但它始终负责把硬件能力组织成可用、可控、可扩展的计算环境。

操作系统的历史脉络

OS 的发展大致可以分成几个阶段。

批处理系统

1950 年代中期到 1960 年代中期,主机时代主要是批处理系统(Batch Systems)。这类系统的重点是把作业排队处理,而不是让用户实时交互。

多道程序系统

1960 年代的迷你计算机(minicomputer)时期出现了多道程序系统(Multiprogramming Systems)。Unix 也在这一时期诞生,背后是 Ken Thompson 和 Dennis Ritchie 的工作。这个阶段标志着 OS 从“把任务排好”开始走向“把多个任务同时组织起来”。

个人计算机时代

1980 年代个人计算机兴起后,OS 面向的对象从大型中心机房转向个人桌面环境。这个时期的代表包括:

  • MS-DOS
  • SunOS
  • ULTRIX
  • Macintosh
  • Windows 1.0 / 2.0
  • IBM AIX
  • HP-UX
  • Minix
  • SGI IRIX
  • NeXTSTEP

互联网时代

1990 年代以后,网络能力变成 OS 的标准配置。这个时期的代表包括:

  • Windows 3.0 / 3.1 / 95 / 98 / NT 3.1 / NT 4.0
  • Linux
  • Solaris 2.0
  • FreeBSD
  • NetBSD
  • OS/2

移动、云与物联网时代

2000 年代以后,OS 又向移动端和嵌入式场景延伸。这个阶段的代表包括:

  • macOS X
  • Windows 2000 / Server 2003 / ME / XP / Vista / 7 / 8 / 10 / 11
  • Android
  • iOS
  • IoT OS

这条历史线的重点不是记年代,而是看出 OS 的职责一直在扩大,从“单机控制”走向“网络化、移动化、普适化”。

为什么要学操作系统

学习 OS 的价值可以从两种思维方式理解。

计算思维

计算思维(Computational Thinking) 是不可或缺的。它本质上就是系统化地拆问题、定义约束、比较方案,再在限制下找可行解。OS 里几乎所有决策都离不开这个过程。

系统思维

操作系统面对的是大型复杂系统。真正的工程问题通常不是“有没有答案”,而是“在资源、性能、可靠性和可维护性之间怎么折中”。OS 是很典型的系统思维训练对象。

Windows Mobile、机器学习系统(ML systems)和 MacOS 这类例子都说明,OS 的影响范围早就不只是在传统 PC 上了。移动设备、AI 基础设施和桌面系统虽然形态不同,但都要面对资源调度、隔离、抽象和可靠性问题。

什么是操作系统

操作系统可以先理解为一个控制应用程序执行的程序。它会决定哪个程序先运行、运行多久、何时挂起,以及在需要时如何换出。

从功能上看,它有两个主角色。

角色含义
资源管理器(resource manager)管理 CPU、内存、磁盘、文件等共享资源,处理冲突请求,并尽量兼顾效率与公平
应用与硬件之间的接口(interface)把应用程序和底层硬件隔离开,向上提供 API,让程序用统一方式申请 OS 服务

这也是为什么应用开发会因为 OS 的存在而简单很多。程序不需要直接面对每一种硬件差异,而是通过 OS 提供的接口去申请资源。

核心服务

OS 的核心服务可以概括成四件事。

  1. 让应用能够在系统上正确、有效地运行。
  2. 让运行中的应用能够使用内存,并在需要时共享内存。
  3. 让运行中的应用能够相互交互。
  4. 让应用能够访问和共享持久化存储中的数据。

这些服务背后的共通问题只有一个:OS 到底用什么机制(mechanism)和策略(policy)把这些事做出来。这里的重点不是“为什么要做”,因为答案通常很明显,而是“怎么做得正确、有效率,并且需要什么硬件支持”。

三个关键词

OS 的核心问题可以整理成三个词。

关键词含义
虚拟化(Virtualization)让每个应用觉得自己独占资源,比如 CPU、内存
并发(Concurrency)多个事件同时发生,并且彼此可能交互
持久化(Persistence)让信息能够长期保存并被反复访问

这三个词基本可以覆盖后面大部分章节的主线。

进程与处理器管理

进程(process)本质上就是正在执行中的程序。进程要完成任务,就需要资源,例如 CPU、内存、I/O 设备、文件和初始数据。进程结束时,OS 还要回收可重复利用的资源。

系统里通常有很多进程,其中既有用户进程,也有 OS、内核(kernel)或系统进程,它们会在一个或多个 CPU 核上并发运行。

OS 在处理器管理上的职责主要包括:

  • 管理和控制应用进程
  • 让进程执行受限操作,例如 I/O
  • 提供“有很多 CPU 可用”的错觉
  • 即使进程不配合,也能重新夺回 CPU 控制权
  • 设计高效的调度器(scheduler)

这里的关键不是“让谁先跑”这么简单,而是要在资源有限的情况下持续维持系统可用。

内存管理

冯·诺伊曼结构 (Von Neumann architecture) 下,运行中的程序要执行,指令和数据必须在物理内存(physical memory)中。

这是什么结构?

笔者之前没了解过OS,因此也不知道这个结构。查询后了解到,冯·诺伊曼结构是一种计算机体系结构,它描述了计算机的基本组成部分和工作原理。它包括以下几个关键组件:

  1. 存储器(Memory):用于存储程序指令和数据。
  2. 控制器(Control Unit):负责从存储器中获取指令,并控制计算机的操作。
  3. 算术逻辑单元(ALU):执行算术和逻辑运算。
  4. 输入/输出设备(I/O Devices):用于与外部世界进行交互。
  5. 总线(Bus):用于连接各个组件,传输数据和指令。

下图为一张冯·诺伊曼结构的示意图:

冯·诺伊曼结构
图 1.2:冯·诺伊曼结构示意图

在有限内存、多个进程并发运行的前提下,OS 的任务就是决定哪些内容应该留在内存里,以便优化 CPU 利用率和用户响应速度。

内存管理的职责包括:

  • 给每个进程提供一个看起来私有的地址空间
  • 控制应用能访问哪些内存位置
  • 在总内存需求超过物理上限时,借助更大但更慢的磁盘
  • 管理空闲空间,并在快用完时从运行中的进程回收部分内存

这部分的本质,是在“隔离”和“共享”之间找平衡。

并发

OS 本身就是并发程序。多个执行逻辑可能同时更新内核内部的数据结构。现代多核系统和多线程程序进一步放大了这个问题,因为共享数据可能被同时访问和修改。

因此,正确处理并发的前提,是使用合适的同步原语(synchronization primitives),并且让硬件和 OS 提供足够的支持。

OS 在并发方面要回答的问题包括:

  • 需要哪些同步原语
  • 这些原语需要硬件和 OS 提供什么支持
  • 如何使用这些原语解决并发问题

如果没有同步,多个线程或多个内核执行路径同时碰共享数据,程序就很容易出错。

文件管理

OS 中负责管理磁盘存储的部分叫文件系统(file system)。它要做的事,是以可靠且高效的方式,把用户创建的数据保存在磁盘上。

文件系统提供的是一种统一、逻辑化的存储视图。它抽象掉物理介质的细节,把文件映射到实际存储位置,并提供给应用创建、访问和管理文件的机制。

文件管理的职责包括:

  • 管理持久化设备
  • 为新建文件寻找合适的存储位置
  • 删除文件时正确回收空间
  • 设计文件系统内部的数据结构,让按文件名访问文件成为可能
  • 降低文件访问的 I/O 成本,因为磁盘访问很慢

设计目标

OS 的设计目标可以概括成几组。

  • 通过抽象让系统更容易使用
  • 在应用之间、以及 OS 与应用之间提供保护
  • 尽量高效地使用系统资源
  • 能适应多种硬件配置
  • 具有较高可靠性,不应因为个别应用或硬件错误就崩溃
  • 保护资源不被未授权用户或软件访问
  • 还要考虑安全性、能效和移动性

这些目标之间往往互相拉扯,所以 OS 工程本身就是一门权衡艺术。

机制与策略

讨论现实系统问题时,一个很重要的设计原则是:机制(mechanism)和策略(policy)要分开看。

  • 机制负责“能做什么”
  • 策略负责“怎么做、何时做、对谁做”

操作系统设计里,这个区分很关键。很多问题并不是缺少能力,而是缺少合适的决策规则。

操作系统结构

从结构上看,OS 一般分成两层感知。

  • 上层是 shell 或命令层,负责用户和 OS 的交互
  • 中间有一组工具函数,供应用程序调用
  • 底层是 kernel,负责管理资源并直接和硬件打交道

OS 架构的意义,就是把一个很复杂的系统组织得可管理、可扩展、可维护。

用户态与内核态

CPU 至少有两种运行模式。

模式特点
内核态(kernel mode)也叫特权态(privilege mode)或监督态(supervisor mode),OS 内核运行时进入这一模式,可以执行机器允许的任何指令
用户态(user mode)应用程序运行时进入这一模式,只能使用部分机器指令,不能干扰其他程序的正常运行

这个区分是 OS 安全性和隔离性的基础。

系统调用

系统调用(system call)是应用程序向 OS 申请资源或服务的机制。系统调用集合构成了 OS 服务的接口,也就是 API。

当系统调用发生时,系统会从用户态切换到内核态,执行对应的内核功能,再通过 trap / return-from-trap 回到用户态。这个过程就是模式切换(mode switch)。

如果没有系统调用,应用程序就很难以受控方式使用受限资源。

单体内核

单体架构(monolithic architecture)是最传统的一类设计。它的基本特点是:OS 的所有组件都在内核里,整个系统像一个大程序一样在特权态中运行。

它的优点是效率高,组件之间可以直接函数调用,共享数据也很方便。

它的缺点也很明显:

  • 体系结构相关代码容易散落在内核各处
  • 一个组件可以直接访问另一个组件的数据和函数
  • 某个组件的修改可能连带影响别的组件
  • 一个组件的 bug 可能波及整个系统
  • 恶意代码也更容易造成损害

Unix、Linux 和 MS-DOS 都属于这一类的代表。

分层架构

分层架构(layered architecture)把功能相近的组件组织成模块,再把模块一层层叠起来。每一层只能和相邻层通信。

优点主要有两个。

  • 结构清晰,容易构建和调试
  • 信息隐藏较好,可以用新的实现替换某一层,而不影响其他层

缺点也很直接。

  • 性能通常不如单体内核
  • 层次怎么划分并不容易
  • 灵活性不足
  • 现实系统往往比层模型更复杂

Windows NT 3.x 的分层实现曾经面临性能偏低的问题。Windows NT 4.0 把部分层从用户空间移到内核空间,做了更紧的集成,从而改善性能。

虚拟机与容器

虚拟机监控器(Virtual Machine Monitor, VMM),也叫 hypervisor,可以放在宿主 OS 上运行,也可以被整合进宿主 OS 的内核中。它负责虚拟化硬件资源,让每个运行中的 OS 都以为自己独占整台机器。

从这个角度看,VMM 本质上就是“OS 的 OS”。

容器(container)技术属于 OS 级虚拟化,它把服务器虚拟化放在操作系统之上。容器里的程序只能看到分配给它的资源。典型例子包括:

  • LXC
  • LXD
  • Solaris Zones
  • Docker
  • Google Containers

如果只从最简化视角看,虚拟机和容器的差别在于:

  • 虚拟机虚拟的是整套硬件环境,里面跑的是完整 OS
  • 容器共享宿主内核,只隔离用户空间所见的资源和环境

微内核架构

微内核(microkernel)把尽可能多的功能从内核空间移到用户空间的服务器进程里,只保留最基础的进程通信和 I/O 控制。

这样做的目的,是把内核做小。

优点:

  • 更容易扩展、移植和规模化
  • 更安全、更可靠,因为内核态代码更少

缺点:

  • 性能通常较差
  • 服务器进程之间的通信要通过内核,消息传递会带来明显开销

很多嵌入式系统会采用微内核思路,因为它们通常更重视可控性、可靠性和较小的内核规模。

模块化架构

现代 OS 往往仍保留单体内核的基本形态,但会把核心组件拆成内核模块(kernel modules)。

模块化方法有几个关键好处:

  • 模块之间有明确定义且受保护的接口
  • 模块都在内核中,通信效率较高
  • 某些功能可以按需动态加载
  • 只加载需要的模块,可以节省内存
  • 模块可单独修改,也更容易扩展

典型例子包括 Solaris、Linux 和传统 Unix 内核。

具体系统例子

几个典型系统可以帮助我们理解现实 OS 架构的混合特征。

  • Windows 系统架构:混合内核(hybrid kernel),带有模块化设计思想
  • Linux 系统架构:整体上偏单体,但支持可加载内核模块
  • Mac OS X / XNU:混合内核,并支持可加载内核扩展
  • Android:在 Linux 内核基础上构建系统架构

这些例子想说明的不是“谁更先进”,而是现实系统通常会把几种架构思想混合起来,用来折中性能、稳定性和扩展性。

结论

如果把这一讲压成一句话,那就是:操作系统本质上是一个资源管理器和抽象层,它要在虚拟化、并发和持久化这三类问题上做出稳定的工程折中,并且通过不同的架构设计去平衡性能、可靠性、扩展性和安全性。

返回目录