第十三章 操作系统 — 软件的核心
导读
当你按下电脑的电源键,几秒钟后,一个功能丰富的桌面出现在屏幕上。你可以同时打开浏览器、音乐播放器和文字处理器,每个程序都在流畅地运行。你可以插入U盘,系统自动识别并挂载。你可以连接Wi-Fi,系统自动配置网络。这一切看似理所当然,但在计算机的早期,每一个操作都需要手动管理硬件的每一个细节。
这一切便利的背后,是操作系统(Operating System, OS)在默默地工作。操作系统是计算机系统中最重要的软件——它管理硬件资源,为应用程序提供服务,是用户和硬件之间的桥梁。没有操作系统,计算机只是一堆无法使用的电子元件。
本章将全面介绍操作系统的基本概念和核心功能。我们将从操作系统的起源讲起,了解它是如何从简单的监控程序演变为复杂的软件系统的;然后深入探讨进程管理、内存管理、文件系统和I/O管理等核心功能;最后了解现代操作系统的设计和发展趋势。通过本章的学习,你将理解操作系统在计算机系统中的核心地位,以及它是如何协调硬件和软件的。
核心概念详解
13.1 操作系统的定义与目标
操作系统是管理计算机硬件和软件资源的系统软件,它是计算机系统中最接近硬件的一层软件。操作系统的核心目标包括:
抽象(Abstraction):为应用程序提供简洁、统一的硬件接口,隐藏硬件的复杂细节
资源管理(Resource Management):高效地分配和管理CPU、内存、磁盘、网络等硬件资源
保护(Protection):防止程序之间的相互干扰,保证系统的安全和稳定
共享(Sharing):允许多个程序共享硬件资源,提高资源利用率
13.2 操作系统的起源
早期计算机:没有操作系统
在1940-1950年代,计算机没有操作系统。程序员直接操作硬件,通过面板上的开关和指示灯来输入程序和查看结果。后来使用穿孔卡片和纸带来输入程序。
每次只能运行一个程序(批处理),程序之间需要人工切换。计算机的利用率极低——大量的时间被浪费在人工操作上。
批处理系统
1950-1960年代,出现了批处理系统(Batch System)。操作员将一组程序(作业)收集起来,一起输入到计算机中。一个专门的监控程序(Monitor)自动按顺序执行这些作业。
监控程序是操作系统的雏形,它提供了基本的作业调度和I/O管理功能。
多道程序设计
1960年代,多道程序设计(Multiprogramming)技术的出现是一个重大突破。内存中同时存放多个程序,当一个程序等待I/O时,CPU切换到另一个程序执行。这大大提高了CPU的利用率。
多道程序设计带来了新的挑战:如何管理内存中多个程序的空间?如何防止程序之间的相互干扰?这些问题催生了操作系统的核心功能——进程管理和内存管理。
分时系统
1960-1970年代,分时系统(Time-Sharing System)使得多个用户可以同时通过终端使用计算机。操作系统为每个用户分配一小段时间片(time slice),轮流执行各用户的程序。由于时间片很短(通常几十毫秒),每个用户都感觉自己在独占计算机。
分时系统的代表是1964年的CTSS(Compatible Time-Sharing System)和1965年的Multics。Multics虽然商业上不算成功,但它的设计理念深刻影响了后来的Unix操作系统。
13.3 Unix的诞生
1969年,贝尔实验室的Ken Thompson和Dennis Ritchie在PDP-7小型机上开发了Unix操作系统。Unix的设计哲学——"做一件事,做好它"(Do one thing and do it well)——深刻影响了后世的软件设计。
Unix的核心创新:
- 层次化文件系统:树状目录结构
- 管道(Pipe):将一个程序的输出作为另一个程序的输入
- Shell:命令行解释器,提供用户与系统交互的界面
- C语言重写:1973年,Unix用C语言重写,成为第一个可移植的操作系统
Unix的衍生版本众多:BSD、System V、Linux、macOS等。今天的主流操作系统中,除了Windows,几乎都可以追溯到Unix的血脉。
13.4 进程管理
进程(Process)是操作系统进行资源分配和调度的基本单位。一个进程包含:
- 程序的代码(文本段)
- 数据(数据段、堆、栈)
- 执行状态(寄存器值、程序计数器)
- 资源(打开的文件、网络连接等)
进程的状态
进程在其生命周期中经历多种状态:
- 新建(New):进程正在被创建
- 就绪(Ready):进程已准备好运行,等待CPU分配
- 运行(Running):进程正在CPU上执行
- 阻塞(Blocked/Waiting):进程等待某个事件(如I/O完成)
- 终止(Terminated):进程执行完毕
进程调度
操作系统的调度器(Scheduler)决定哪个就绪进程获得CPU。常见的调度算法:
- 先来先服务(FCFS):按到达顺序分配CPU。简单但不公平。
- 最短作业优先(SJF):优先执行预计运行时间最短的进程。平均等待时间最短,但可能导致长作业饥饿。
- 时间片轮转(Round Robin):每个进程分配一个时间片,时间片用完后切换到下一个进程。公平但上下文切换开销大。
- 优先级调度:按优先级分配CPU。高优先级进程先执行。可能导致低优先级进程饥饿。
- 多级反馈队列:结合优先级和时间片,根据进程的行为动态调整优先级。现代操作系统常用的调度策略。
上下文切换
当调度器决定切换进程时,需要保存当前进程的状态(寄存器、PC等)到进程控制块(PCB),然后加载下一个进程的状态。这个过程称为上下文切换(Context Switch)。
上下文切换是有开销的——它消耗CPU时间但不做有用的工作。操作系统的设计目标之一是尽量减少不必要的上下文切换。
13.5 内存管理
操作系统的内存管理负责跟踪内存的使用情况,决定哪些数据应该放在内存中,以及如何为进程分配内存空间。
连续分配
最早的内存管理方式是连续分配——每个进程占用一块连续的内存空间。
问题:
- 碎片:随着进程的创建和终止,内存中出现许多小的空闲块(外部碎片),无法满足大进程的需求
- 重定位:进程在内存中的位置可能变化,需要修改程序中的地址
分页(Paging)
分页将物理内存和虚拟内存都划分为固定大小的块(页面),通常为4KB。进程的虚拟页面可以映射到任意物理页面,不要求连续。
分页解决了外部碎片问题,但引入了内部碎片(最后一页可能没有完全利用)。
分段(Segmentation)
分段将程序的地址空间按逻辑划分为不同大小的段(代码段、数据段、堆、栈等)。每个段有独立的基地址和长度限制。
分段更符合程序的逻辑结构,但容易产生外部碎片。
虚拟内存
如前一章所述,虚拟内存让每个进程都以为自己独占整个地址空间。当物理内存不足时,操作系统将不常用的页面交换到磁盘上的交换空间(Swap Space)。
虚拟内存的关键技术:
- 页表(Page Table):记录虚拟页面到物理页面的映射
- TLB:缓存最近的地址转换
- 缺页中断(Page Fault):当访问的页面不在内存中时触发,操作系统将页面从磁盘加载到内存
13.6 文件系统
文件系统(File System)是操作系统管理持久存储设备上数据的机制。它提供了文件的创建、读取、写入、删除等操作,以及目录结构来组织文件。
文件的概念
文件(File)是一组相关信息的集合,有唯一的名称(文件名)。文件可以是程序、数据、文档、图片等任何形式的数据。
每个文件有一组属性(Attributes):名称、类型、位置、大小、保护信息、创建时间等。
目录结构
目录(Directory)是包含文件和其他目录的特殊文件。目录结构通常是树状的:
/
├── bin/ ; 可执行文件
├── etc/ ; 系统配置文件
├── home/ ; 用户主目录
│ ├── alice/
│ └── bob/
├── usr/ ; 用户程序
└── var/ ; 可变数据文件系统的实现
文件系统需要管理两件事:文件的内容(数据块)和文件的元数据(文件名、大小、权限等)。
常见的文件系统实现方式:
- FAT(File Allocation Table):使用文件分配表跟踪文件的磁盘块。简单但效率低。
- NTFS(New Technology File System):Windows的文件系统,支持权限、加密、压缩等高级功能。
- ext4:Linux常用的文件系统,使用inode来存储文件元数据。
- APFS(Apple File System):macOS和iOS的文件系统,针对SSD优化。
13.7 I/O管理
I/O设备种类繁多(磁盘、键盘、显示器、网络接口等),速度差异巨大。操作系统的I/O管理负责统一管理和调度这些设备。
I/O控制方式
- 程序控制I/O(Programmed I/O):CPU不断轮询设备状态,直到操作完成。效率低,CPU被浪费。
- 中断驱动I/O(Interrupt-Driven I/O):设备完成操作后向CPU发送中断信号。CPU不需要等待,可以做其他事情。
- DMA(Direct Memory Access):DMA控制器直接在设备和内存之间传输数据,不需要CPU参与。传输完成后才中断CPU。效率高,适合大批量数据传输。
设备驱动程序
设备驱动程序(Device Driver)是操作系统与硬件设备之间的软件接口。每个设备都有对应的驱动程序,它将操作系统的通用I/O请求转换为设备特定的控制命令。
设备驱动程序的设计是操作系统中最复杂的部分之一,因为需要处理各种各样的硬件差异和异常情况。
13.8 操作系统内核
内核(Kernel)是操作系统的核心部分,运行在内核模式,拥有对硬件的完全访问权限。
内核的类型
- 宏内核(Monolithic Kernel):所有操作系统服务都在内核空间运行。速度快,但一个模块的错误可能导致整个系统崩溃。代表:Linux、传统Unix。
- 微内核(Microkernel):只保留最基本的功能在内核空间(进程通信、基本调度、内存管理),其他服务(文件系统、设备驱动等)在用户空间运行。稳定性好,但进程间通信开销大。代表:MINIX、QNX。
- 混合内核(Hybrid Kernel):结合宏内核和微内核的特点。代表:Windows NT、macOS(XNU)。
系统调用
系统调用(System Call)是应用程序请求操作系统服务的接口。当程序需要读写文件、创建进程、分配内存等操作时,通过系统调用陷入内核,由内核代为执行。
常见的系统调用:
read()/write():读写文件open()/close():打开/关闭文件fork()/exec():创建/执行进程malloc()/free():内存分配(通常通过库函数封装)socket():网络通信
13.9 操作系统的启动过程
当计算机通电时,执行以下启动过程:
BIOS/UEFI:加电自检(POST),初始化硬件,找到启动设备
引导加载器(Bootloader):如GRUB,加载操作系统内核到内存
内核初始化:初始化内存管理、进程调度、设备驱动等子系统
挂载根文件系统:将磁盘上的根文件系统挂载到内存
启动init进程:第一个用户进程(PID=1),负责启动其他系统服务
系统就绪:所有服务启动完毕,系统进入可用状态
13.10 现代操作系统的发展趋势
移动操作系统
iOS和Android主导了移动设备市场。它们针对触摸屏、电池寿命、传感器等移动特性进行了优化。
云操作系统
云计算平台(如AWS、Azure、GCP)提供了虚拟化的计算资源。容器技术(Docker、Kubernetes)进一步抽象了操作系统环境。
实时操作系统
实时操作系统(RTOS)保证在确定的时间内响应事件,用于嵌入式系统、工业控制、航空航天等领域。
分布式操作系统
分布式操作系统管理多台计算机的资源,使它们像一个统一的系统一样工作。区块链、分布式数据库等技术是这一方向的探索。
重要知识点
知识点一:操作系统是硬件和软件之间的桥梁
操作系统抽象了硬件的复杂性,为应用程序提供统一的接口。
知识点二:进程是资源分配的基本单位
进程管理包括进程创建、调度、同步和通信。调度算法决定了CPU时间的分配。
知识点三:虚拟内存提供了地址空间的抽象
分页和分段技术使得每个进程都以为自己独占整个地址空间,同时实现了内存保护。
知识点四:文件系统管理持久存储数据
文件系统提供了文件和目录的抽象,管理磁盘空间的分配和回收。
知识点五:I/O管理统一了设备访问
中断驱动和DMA技术提高了I/O效率,设备驱动程序屏蔽了硬件差异。
常见误区
误区一:"操作系统只是一个大程序"
操作系统不是一个单一的程序,而是一个复杂的软件系统,包含内核、系统库、系统工具等多个组成部分。内核是操作系统的核心,但不是全部。
误区二:"Linux就是Unix"
Linux是一个受Unix设计启发但独立实现的操作系统内核。它在API层面兼容Unix(POSIX标准),但代码完全是新写的。严格来说,Linux是"类Unix"(Unix-like)系统。
误区三:"微内核一定比宏内核好"
微内核在可靠性方面有优势,但性能开销较大。宏内核性能好但稳定性较差。没有绝对的优劣,只有适合不同场景的设计选择。
误区四:"操作系统越新越好"
操作系统的选择取决于应用场景。服务器可能使用经过长期验证的稳定版本,嵌入式系统可能使用精简的RTOS,桌面用户可能追求最新的功能。
实践应用
应用一:观察进程状态
在Linux系统中使用以下命令观察进程:
ps aux:列出所有进程top:实时查看进程状态htop:更友好的进程查看工具
应用二:探索文件系统
在Linux系统中:
df -h:查看磁盘使用情况du -sh *:查看当前目录下各文件/目录的大小mount:查看挂载的文件系统
应用三:使用系统调用
编写一个简单的C程序,使用系统调用:
#include <unistd.h>
#include <fcntl.h>
int main() {
int fd = open("test.txt", O_CREAT | O_WRONLY, 0644);
write(fd, "Hello, OS!\n", 12);
close(fd);
return 0;
}应用四:比较不同操作系统
研究Linux、Windows和macOS在以下方面的差异:
- 文件系统
- 进程管理
- 用户界面
- 软件包管理
本章小结
本章全面介绍了操作系统的基本概念和核心功能:
操作系统的定义:管理硬件资源、为应用程序提供服务的系统软件。
操作系统的起源:从批处理到多道程序设计,从分时系统到现代操作系统。
Unix的影响:层次化文件系统、管道、Shell等创新深刻影响了后世。
进程管理:进程的状态、调度算法、上下文切换。
内存管理:分页、分段、虚拟内存。
文件系统:文件和目录的管理,FAT、NTFS、ext4等实现。
I/O管理:程序控制I/O、中断驱动I/O、DMA。
内核:宏内核、微内核、混合内核的设计选择。
系统调用:应用程序请求操作系统服务的接口。
启动过程:从BIOS到用户界面的完整流程。
操作系统是计算机系统中最核心的软件。但在操作系统之上,还有更高层次的抽象——高级编程语言。在下一章中,我们将学习高级语言如何让程序员摆脱机器语言的束缚,用更接近人类思维的方式编写程序。