跳转到内容

操作系统基础

建议学习 90-120 分钟更新于 2026/4/6

操作系统是计算机系统中最核心的软件之一。

它向下管理 CPU、内存、磁盘、输入输出设备等硬件资源,向上为用户和应用程序提供稳定、友好的运行环境。学习操作系统,本质上是在理解计算机如何把有限的硬件资源组织起来,并让多个程序看起来可以同时、稳定、有序地运行。

这篇笔记主要整理:

  • 操作系统的作用、特征、功能和分类。
  • 进程的组成、状态和进程关系。
  • 前驱图、进程资源图、同步与互斥、信号量。
  • 死锁、银行家算法和线程。
  • 分区存储、页式存储、段式存储和段页式存储。

操作系统的核心作用可以概括为两点:

  • 通过资源管理提高计算机系统效率。
  • 改善人机交互,为用户提供友好的工作环境。

没有操作系统时,应用程序需要直接面对硬件。这样不仅开发复杂,也很难保证多个程序之间互不干扰。操作系统把底层硬件抽象成更容易使用的接口,让应用程序可以通过统一方式申请资源、读写文件、创建进程、访问设备。

操作系统通常具有四个基本特征。

特征含义
并发性多个程序在同一时间段内交替运行,看起来像同时执行
共享性多个进程可以共同使用系统中的资源
虚拟性把一个物理资源抽象成多个逻辑资源,例如虚拟内存
不确定性程序执行顺序和完成时间可能受到调度、资源竞争等因素影响

并发性和共享性是操作系统最基本的两个特征。

如果多个程序可以并发执行,就必然涉及资源共享;而资源共享又会带来同步、互斥、死锁等问题。

操作系统主要负责五类管理工作。

功能说明
进程管理创建、调度、阻塞、唤醒和终止进程
存储管理管理内存分配、地址转换和虚拟存储
文件管理管理文件的创建、删除、读写、目录和权限
设备管理管理输入输出设备,提高设备利用率
作业管理管理用户提交的作业,组织作业执行流程

可以简单理解为:操作系统负责让程序能运行、让内存能分配、让文件能保存、让设备能使用。

常见操作系统可以按使用场景和设计目标分类。

类型特点
批处理操作系统用户提交作业后由系统成批处理,交互性较弱
分时操作系统多个用户轮流使用 CPU 时间片,强调交互性
实时操作系统要求在规定时间内快速响应,常用于工业控制等场景
网络操作系统支持网络通信和网络资源共享
分布式操作系统多台物理分散的计算机协同工作,对用户表现为统一系统
微机操作系统面向个人计算机,例如 Windows、macOS、Linux 桌面版
嵌入式操作系统面向嵌入式设备,强调资源占用小、稳定性高

不同类型的操作系统侧重点不同,但底层都离不开进程、内存、文件和设备管理。

计算机启动时,操作系统并不是一开始就在运行。

一个简化的启动流程如下:

BIOS / UEFI引导加载程序操作系统内核用户环境
启动流程可以理解为:硬件自检后找到引导程序,再由引导程序把操作系统内核加载起来。
BIOS / UEFI
-> 主引导记录 / 引导加载程序
-> 加载操作系统内核
-> 初始化系统服务
-> 进入用户环境

传统说法中常见的流程是:

BIOS -> 主引导记录 -> 操作系统

BIOS 或 UEFI 负责完成硬件自检,并找到可启动设备。引导加载程序再负责把操作系统内核加载到内存中,最终由操作系统接管整个系统。

进程是正在运行的程序实例。

程序本身只是静态文件,只有被加载到内存并开始执行后,才会形成进程。操作系统以进程为单位进行资源分配和管理。

一个进程通常包括:

组成说明
进程控制块 PCB进程的唯一标识,保存进程状态、调度信息、资源信息等
程序描述进程要执行的指令
数据进程运行过程中需要使用或产生的数据

其中 PCB 是操作系统管理进程的关键。

操作系统并不是直接“记住一个程序”,而是通过 PCB 记录这个进程是谁、处于什么状态、占用了哪些资源、下一步应该如何调度。

进程最基础的状态模型是三态模型。

就绪运行等待调度时间片到等待事件事件发生
三态模型只关注就绪、运行、等待三个核心状态,挂起状态是在此基础上的扩展。
就绪 -> 运行 -> 等待
^ | |
| | v
+-------+-------+

更清晰地说:

状态含义
就绪进程已经具备运行条件,只差 CPU
运行进程正在 CPU 上执行
等待进程正在等待某个事件或资源,例如 I/O 完成

状态转换可以这样理解:

就绪 --调度--> 运行
运行 --时间片到--> 就绪
运行 --等待事件--> 等待
等待 --事件发生--> 就绪

五态模型是在三态模型基础上增加了挂起状态。

状态含义
活跃就绪在内存中,等待 CPU 调度
活跃阻塞在内存中,等待事件发生
静止就绪被挂起,不在内存中,但已经具备运行条件
静止阻塞被挂起,不在内存中,同时还在等待事件
运行正在 CPU 上执行

挂起通常来自人为干预或系统调度策略。进程被挂起后进入静止状态,需要被激活后才能重新回到活跃状态。

前驱图用于表示任务之间的先后关系。

它可以说明哪些任务可以并行执行,哪些任务必须等待前置任务完成。

例如:

ABCDE
A、B、C 可以并行执行,D 必须等待它们全部完成,E 再等待 D 完成。
A ─┐
B ─┼──> D ───> E
C ─┘

这个前驱图表示:

  • A、B、C 之间没有依赖关系,可以并行执行。
  • D 必须等 A、B、C 全部完成后才能执行。
  • E 必须等 D 完成后才能执行。

所以前驱图主要确定两件事:

  • 任务之间能否并行。
  • 任务之间的先后顺序。

进程资源图用于表示进程和资源之间的分配、请求关系。

常见符号:

符号含义
P进程
R资源
资源框中的圆点该类资源的实例数量
R -> P资源已经分配给进程
P -> R进程正在请求资源

例如:

R1R2P1P2P3
资源指向进程表示已经分配,进程指向资源表示正在请求。若多个进程形成循环等待,就可能出现死锁。
R1 -> P1 -> R2

可以理解为:

  • R1 中的某个资源已经分配给 P1。
  • P1 还需要请求 R2 才能继续执行。

节点可以分为两类:

类型含义
阻塞节点进程请求的资源已经全部分配完,暂时无法获得资源
非阻塞节点进程请求的资源仍有剩余,可以继续分配

当进程资源图中所有进程都是阻塞节点,并且形成循环等待关系时,系统就可能进入死锁状态。

同步和互斥都是为了处理并发环境下的进程协作问题,但它们关注点不同。

互斥指多个进程不能同时访问某个临界资源。

临界资源是一次只允许一个进程访问的资源。例如:

  • 打印机。
  • 公共变量。
  • 某些共享文件。
  • 数据库中的某个共享记录。

如果多个进程同时访问临界资源,可能导致数据错误、文件损坏或程序异常。

互斥的目标是:

同一时刻,只允许一个进程进入临界区。

互斥信号量通常只有两个值:

1:资源空闲,可以进入
0:资源被占用,需要等待

可以把互斥信号量想象成门锁。门开着表示可以进入,门锁上表示里面有人,其他人必须等待。

同步指多个进程按照某种顺序协调执行。

它关注的不是“谁不能同时访问”,而是“谁必须先执行,谁必须后执行”。

例如生产者和消费者:

生产者先生产数据
消费者后消费数据

如果没有数据,消费者就应该等待;如果缓冲区满了,生产者也应该等待。

同步信号量可以用来表示某类资源或条件的数量。例如餐厅里的餐桌数量有限,顾客需要先获得餐桌才能吃饭。餐桌数量就是一个同步信号量。

信号量是一种用于进程同步和互斥的机制。

它通常配合两个操作使用:

  • P 操作:申请资源。
  • V 操作:释放资源。
P:S = S - 1S < 0 ?进入阻塞队列V:S = S + 1S <= 0 ?否:继续执行是:唤醒否:继续执行
P 操作负责申请资源,资源不足时阻塞;V 操作负责释放资源,并在需要时唤醒等待进程。

P 操作表示申请资源。

S = S - 1

判断规则:

条件结果
S >= 0说明资源可用,进程继续执行
S < 0说明资源不足,进程进入阻塞队列

也可以这样理解:

先尝试拿走一个资源。
如果拿完后资源数量仍然够用,就继续执行。
如果资源不够,就阻塞等待。

V 操作表示释放资源。

S = S + 1

判断规则:

条件结果
S > 0没有进程因该资源阻塞,当前进程继续执行
S <= 0有进程正在等待该资源,需要唤醒一个阻塞进程

也可以这样理解:

释放一个资源。
如果有人在等,就唤醒一个等待进程。
如果没人等,资源数量增加。

死锁是指多个进程因为竞争资源而互相等待,最终都无法继续执行。

死锁产生通常需要同时满足四个必要条件:

条件含义
互斥条件资源一次只能被一个进程使用
请求并保持条件进程已经占有资源,同时还在请求其他资源
不可剥夺条件已分配给进程的资源不能被系统强制剥夺
循环等待条件多个进程之间形成资源等待环

例如:

P1 占有 R1,等待 R2
P2 占有 R2,等待 R1

此时 P1 和 P2 都在等待对方释放资源,系统进入死锁。

银行家算法是一种避免死锁的算法。

它的核心思想是:在分配资源之前,先判断这次分配是否会让系统进入不安全状态。

如果分配后系统仍然安全,就允许分配;如果可能进入不安全状态,就暂时不分配。

它关注几个概念:

概念含义
Available当前系统可用资源数量
Max每个进程最多需要的资源数量
Allocation已经分配给每个进程的资源数量
Need每个进程还需要的资源数量

其中:

Need = Max - Allocation

银行家算法并不是等死锁发生后再处理,而是在资源分配前尽量避免系统走向死锁。

传统进程有两个重要属性:

  • 进程是拥有资源的独立单位。
  • 进程是可独立调度和分配的基本单位。

引入线程后,这两个属性被拆开:

概念作用
进程拥有资源的基本单位
线程独立调度的最小单位

同一进程中的多个线程可以共享进程资源,例如:

  • 代码段。
  • 全局变量。
  • 打开的文件。
  • 堆空间。

但线程也有自己的私有数据,例如:

  • 程序计数器。
  • 寄存器上下文。
  • 栈空间。

线程的引入可以减少进程切换开销,提高并发执行效率。

存储管理主要解决一个问题:

如何把程序合理地放入内存,并让 CPU 正确访问它。

程序运行时往往不能简单地一次性完整装入内存。操作系统需要负责内存分配、地址转换、内存保护和虚拟存储。

常见存储管理方式包括:

  • 分区存储。
  • 页式存储。
  • 段式存储。
  • 段页式存储。

分区存储把内存划分成若干区域,每个进程装入一个分区。

常见方式:

方式特点
固定分区分区大小固定,实现简单,但容易造成内部碎片
可变分区分区大小按进程需求动态分配,利用率更高,但容易产生外部碎片

内部碎片指分区内部没有被使用的空间。

外部碎片指空闲空间分散在内存各处,虽然总量够,但无法形成连续空间。

页式存储是一种常见的内存管理方式。

它把程序的逻辑地址空间划分为大小相等的页,同时把物理内存划分为大小相等的块。页和块大小相同,常见大小是 4KB。

程序运行时,不需要连续存放在物理内存中。不同页面可以离散地放入不同内存块,再通过页表建立映射关系。

页号page页内地址offset页表页 0 -> 块 5页 1 -> 块 2页 2 -> 块 8页 3 -> 块 1块号frame页内地址offset查表拼接逻辑地址物理地址
逻辑地址中的页号用于查页表,得到物理块号;页内地址保持不变,和块号拼接成物理地址。
逻辑页 -> 页表 -> 物理块

页式存储的好处是:

  • 不要求程序连续存放。
  • 减少外部碎片。
  • 便于实现虚拟内存。

逻辑地址是程序看到的地址,也可以理解为 CPU 生成的虚拟地址。

物理地址是内存单元在真实物理内存中的地址。

程序访问内存时,并不是直接拿逻辑地址访问物理内存,而是由操作系统和硬件共同完成地址转换。

逻辑地址 -> 地址转换 -> 物理地址

在页式存储中,逻辑地址通常分为:

页号 + 页内地址

页号用于查页表,找到对应的物理块号。

页内地址表示在该页内部的偏移量。

地址转换过程可以简化为:

逻辑地址 = 页号 + 页内地址
页号 -> 查页表 -> 块号
物理地址 = 块号 + 页内地址

页号决定数据在哪个物理块中,页内地址决定数据在这个块中的具体位置。

段式存储按照程序的逻辑结构划分内存。

例如:

  • 代码段。
  • 数据段。
  • 栈段。
  • 堆段。

段式存储中的逻辑地址通常由两部分组成:

段号 + 段内地址

段式存储更符合程序员对程序结构的理解,但每个段长度不固定,容易产生外部碎片。

段页式存储结合了段式和页式的特点。

它先按逻辑结构分段,再把每个段划分为页。

地址结构可以理解为:

段号 + 页号 + 页内地址

段页式存储的特点:

  • 保留段式存储的逻辑结构。
  • 利用页式存储减少外部碎片。
  • 地址转换过程更复杂。

操作系统基础可以先抓住三条主线:

  • 进程管理:解决多个程序如何并发执行。
  • 存储管理:解决程序如何装入内存并正确访问。
  • 资源管理:解决多个进程如何共享有限资源。

进程、线程、同步、互斥、信号量、死锁和页式存储,是学习操作系统时最重要的一组基础概念。

真正理解这些概念后,再看 Linux、数据库、后端服务、并发编程和容器技术,很多底层问题都会更容易串起来。