第三章:操作系统——看不见的管家
【上章回顾】上一章我们认识了 CPU 和 GPU——那个每秒能执行数十亿条指令的"大厨",和那个靠流水线并行取胜的"工厂车间"。但你有没有想过:谁来决定 CPU 什么时候算哪件事?谁来分配内存给不同的程序?谁让你可以一边听歌一边写代码,还能随时切换窗口?
【本章目标】这一章,我们来认识那个"看不见的管家"——操作系统。它不会出现在你的桌面上,却决定了你电脑上发生的一切。
章节引入:那 0.5 秒里谁在忙?
你早上打开电脑,双击 Chrome 图标,0.5 秒后浏览器出现了。
看起来平平无奇,对吧?
但如果你仔细想想,就会发现这里面藏着一连串问题:
- Chrome 的程序文件在硬盘上,谁把它"搬"到了内存里?
- 内存里同时还有你昨晚没关掉的 VS Code、QQ 音乐、微信——谁决定给 Chrome 分多少内存?
- CPU 只有 8 个核心,但你有十几个程序在跑,谁来排队?
- 你一边下载文件一边刷微博,网络带宽是怎么分配的?
这些问题,统统由同一个角色来回答——操作系统(Operating System,简称 OS)。
预计阅读时间:45 分钟
读完本章你会理解:
- 没有操作系统,硬件只是一堆废铜烂铁
- 操作系统如何用"进程"和"线程"来管理多任务
- 文件系统是什么,为什么格式化硬盘会"丢数据"
- 驱动程序为什么会让你的鼠标不灵、显卡不工作
3.1 没有操作系统会怎样
想象一个没有服务员的餐厅
假设你去一家餐厅吃饭,推开门发现——没有服务员,没有领位,没有厨师长协调出菜顺序。厨房里站着几个大厨(CPU),仓库里有食材(硬盘),桌上有餐具(内存),但你不知道该坐哪儿,没人接单,厨师们也不知道先做哪桌的菜,收银台也没人。
这就是没有操作系统的计算机。
硬件是有的:CPU 会算,内存能存,硬盘有数据。但没有一个角色来统筹协调,一切都是混乱的。
每个想用这台电脑的程序,都得自己想办法:
- 自己写代码去读硬盘
- 自己管理内存,避开其他程序占用的地址
- 自己和显卡、网卡通信
- 还要防止自己和别的程序互相踩踏
这在早期的计算机上确实是这样的。1940-1950 年代,程序员需要写"裸机程序",直接控制硬件,每个程序都得解决所有底层问题。后来人们意识到,这些重复劳动可以被抽象成一个公共的"中间层"——操作系统就诞生了。
操作系统是什么
操作系统是硬件和应用程序之间的一层软件,负责管理资源、提供服务、保护安全。
你的电脑上跑着的,可能是 Windows 11、macOS Sequoia,或者某个 Linux 发行版(比如 Ubuntu)。手机上是 Android 或 iOS。这些,都是操作系统。
操作系统做的事情可以分成三大类:
① 资源管理
操作系统管理着计算机的所有资源:CPU 时间、内存空间、磁盘读写、网络带宽。每个应用程序需要这些资源时,不能自己去抢,而是向操作系统申请。操作系统统一调度,防止冲突。
② 提供抽象
操作系统把复杂的硬件操作包装成简单的接口。你写代码时调用 open("file.txt") 就能打开文件——你不需要知道文件存在磁盘的第几个扇区、用的是什么文件系统。这就是操作系统提供的抽象(Abstraction)。
③ 保护隔离
操作系统确保每个程序在自己的"沙箱"里运行,不能随意访问其他程序的内存,也不能绕过权限直接操作硬件。这就是为什么一个崩溃的程序通常不会把整个系统搞挂。
内核:操作系统的核心
操作系统本身也是软件,分层结构如下:
最核心的部分叫做内核(Kernel),它直接和硬件打交道。内核是权限最高的程序,它运行在"内核态(Kernel Mode)",可以执行任意硬件指令。
而普通应用程序(Chrome、微信、你写的 Python 脚本)运行在"用户态(User Mode)",权限受限,不能直接访问硬件。想访问硬件,就得通过**系统调用(System Call)**请求内核代劳。
你的应用程序(Chrome、微信、VSCode)
↕ 系统调用(System Call)
操作系统内核(进程管理、内存管理、文件系统、驱动)
↕ 驱动程序接口
硬件(CPU、内存、硬盘、显卡、网卡……)
这个分层设计非常关键:一方面保证了安全(应用程序不能随便搞坏系统),另一方面简化了开发(程序员不用懂硬件细节)。
❌ 常见误区澄清
❌ "操作系统就是桌面界面" → ✅ 桌面(Windows 的 Explorer、macOS 的 Finder)只是操作系统的一个应用层组件,不是核心。Linux 服务器通常没有图形界面,但操作系统照常运行。
❌ "重装系统就能修好所有问题" → ✅ 重装系统解决的是软件层面的问题(系统文件损坏、病毒、配置混乱)。硬件故障(内存坏块、硬盘损坏)重装没用。
🔧 动手观察:看看你的系统在干什么
Windows 用户:按下 Ctrl + Shift + Esc 打开任务管理器,切到"详细信息"选项卡。你会看到几十甚至上百个进程在运行,其中大部分你根本没有主动启动。这些都是操作系统本身的组件,以及各种后台服务。
macOS 用户:打开"活动监视器"(Spotlight 搜索 Activity Monitor),同样能看到大量系统进程。注意看"用户"列,很多进程的用户名是 root 或 _windowserver,这些是操作系统本身的进程。
注意:看看有多少进程在运行,但 CPU 总使用率可能只有 5-10%。这说明操作系统调度非常高效——大部分进程在"等待",只有真正需要运行的才占用 CPU。
✓ 本节要点
- ✓ 操作系统是硬件和应用程序之间的中间层,负责管理资源、提供抽象、保护隔离
- ✓ 内核是操作系统最核心的部分,运行在特权级别(内核态),拥有最高硬件权限
- ✓ 应用程序通过"系统调用"向操作系统请求服务,而不是直接操控硬件
- ✓ 桌面界面只是操作系统的一个组件,不是操作系统本身
3.2 进程与线程:任务管理器的秘密
你真的"同时"在做多件事吗?
打开任务管理器,你会看到 Chrome 占着 15% 的 CPU,同时 VS Code 也在跑,QQ 音乐还在播歌。
问题来了:你的 CPU 就 8 个核心,凭什么能同时服务这么多程序?
答案是:大多数情况下,它们并不是真的"同时"在跑——而是在极快速地轮流。
这就像一个大厨(单核 CPU)在同时接待 10 桌客人。他并不是同时炒 10 道菜,而是:切一会儿 A 桌的菜,放下刀,去翻一翻 B 桌的锅,再去 C 桌打个酱油……因为切换速度极快(毫秒级),每桌客人都感觉"好像一直有人在做我的菜"。
这种机制叫做时间分片(Time Slicing),是现代操作系统多任务的基础。
进程:程序的运行实例
**程序(Program)**是存在硬盘上的可执行文件,比如 chrome.exe。
**进程(Process)**是程序被载入内存、正在运行的实体。
举个例子:Chrome 的程序文件只有一份,但你可以开两个 Chrome 窗口,它们是两个独立的进程。Word 的程序文件只有一份,但你打开三个文档,就有三个 Word 进程。
每个进程有自己的:
- 独立内存空间:进程 A 不能直接读写进程 B 的内存(除非通过专门的"进程间通信"机制)
- 独立文件描述符:打开了哪些文件、网络连接
- 独立状态:每个进程都有自己的"当前运行到哪了"的记录
这就是"隔离"的意义:一个进程崩溃,不会直接连累其他进程。
硬盘上:chrome.exe(一份可执行文件)
↓ 双击打开
内存里:
┌──────────────────────────┐
│ 进程 A:Chrome 窗口 1 │ ← 独立内存空间
│ 代码 | 数据 | 堆 | 栈 │
└──────────────────────────┘
┌──────────────────────────┐
│ 进程 B:Chrome 窗口 2 │ ← 另一块独立内存空间
│ 代码 | 数据 | 堆 | 栈 │
└──────────────────────────┘
线程:进程内部的"工人"
进程是资源的拥有者,但真正在 CPU 上执行的单位是线程(Thread)。
一个进程可以包含多个线程,这些线程共享同一块内存,但可以同时在不同 CPU 核心上运行。
还是用餐厅类比:进程是"一桌客人的整个订单系统",线程是"处理这桌订单的具体工作人员"。一桌大型聚餐,可以同时有人上菜、有人斟酒、有人收碟——这就是多线程。
以你熟悉的场景为例:你在 Chrome 里打开一个网页,Chrome 内部大概会有这些线程同时工作:
- 渲染线程:解析 HTML、CSS,画出界面
- JavaScript 引擎线程:执行网页上的 JS 代码
- 网络线程:下载图片和其他资源
- UI 线程:处理你的鼠标点击
这四件事真的可以同时发生,分配给不同的 CPU 核心,这就是为什么现代浏览器"感觉很流畅"。
进程调度:谁先上 CPU?
操作系统的**调度器(Scheduler)**决定哪个进程/线程下一个上 CPU 执行。
调度是个复杂的问题,这里说几个关键概念:
优先级(Priority):每个进程有优先级,高优先级的进程更频繁地获得 CPU 时间。操作系统的关键进程(比如处理键盘输入的进程)优先级极高,确保你按下按键立刻有反应。
时间片(Time Slice/Quantum):每次分配给一个进程的 CPU 时间通常是几毫秒到几十毫秒。时间片用完,调度器强制切换到下一个进程。
上下文切换(Context Switch):从一个进程切换到另一个进程时,操作系统需要保存当前进程的"状态"(所有寄存器的值、程序运行到哪了),载入下一个进程的状态。这个操作本身需要消耗 CPU 时间,是有开销的。
这就是为什么同时运行太多程序会让电脑变慢:不是因为"内存不够"(那是另一个问题),而是调度器需要做更多上下文切换,总开销增加。
进程状态:不是每个进程都在"跑"
一个进程在任意时刻,处于以下几种状态之一:
创建 ──→ 就绪(Ready)──→ 运行(Running)
↑ ↓
└──────── 等待(Waiting)
(等 IO、等网络、等用户输入)
运行 ──→ 结束(Terminated)
就绪:准备好了,等待 CPU 调度 运行:正在 CPU 上执行 等待(阻塞):在等某个事件(比如等硬盘读取完成),这时 CPU 可以去跑别的进程
这就是为什么操作系统能高效利用 CPU:当进程 A 在等硬盘数据(IO 操作,可能要几毫秒),调度器立刻把 CPU 给进程 B 用。你感觉两件事"同时"在发生,其实是 CPU 在"空隙时间"做了别的事。
❌ 常见误区澄清
❌ "多核 CPU 就是多个 CPU 焊在一起" → ✅ 多核 CPU 是单芯片上集成多个运算核心,共享缓存和内存控制器,延迟比多 CPU 系统低得多。
❌ "关掉后台进程一定能让电脑变快" → ✅ 只有实际消耗资源的后台进程才值得关。很多进程处于"等待"状态,CPU 占用几乎为 0,关掉它们效果有限。真正拖慢电脑的是高 CPU/内存占用的进程。
🔧 动手观察:进程状态的实时观察
打开任务管理器(Windows)或活动监视器(macOS),观察以下几点:
CPU 列:大多数进程 CPU 占用是 0%,只有少数在用。这说明大部分进程在"等待"状态,没在跑。
内存列:每个进程都占用独立的内存。注意 Chrome——如果你开了很多标签页,它的内存占用可能惊人地高,因为现代 Chrome 给每个标签开一个进程(为了隔离稳定性)。
Windows 用户额外操作:打开命令提示符,输入:
tasklist /fo table | more可以看到所有进程的 PID(进程 ID)、内存占用等信息。
观察一个程序从打开到关闭:打开计算器,在任务管理器里找到它的进程。关掉计算器,看进程消失。这就是进程的完整生命周期。
✓ 本节要点
- ✓ 进程是程序的运行实例,每个进程有独立内存空间,相互隔离
- ✓ 线程是进程内部的执行单位,同一进程的多个线程共享内存,可以真正并行运行
- ✓ 操作系统用"时间分片"实现多任务,CPU 极快地在进程间切换,造成"同时运行"的错觉
- ✓ 进程有就绪、运行、等待三种主要状态,CPU 利用率高的关键在于等待时让出 CPU
3.3 文件系统:电脑如何记住一切
"删除"之后数据去哪了?
你把一个文件拖进回收站,清空,文件"消失"了。
但是——数据真的没了吗?
答案是:没有,至少短期内没有。
这就要从文件系统说起。
文件系统是什么
硬盘,从物理层面看,是一大片可以存储 0 和 1 的空间,被划分成固定大小的"扇区(Sector)",传统上每个扇区 512 字节,现代硬盘通常是 4096 字节。
一个 2TB 的硬盘,有大约 4 亿个扇区。问题来了:你怎么知道哪些扇区属于哪个文件?
文件系统(File System)就是解决这个问题的。它是一套管理磁盘空间的规则和数据结构,让操作系统知道:
- 哪些扇区是空闲的
- 哪些扇区属于哪个文件
- 文件的名字、大小、创建时间等元数据存在哪
常见的文件系统有:
- NTFS:Windows 默认文件系统,支持大文件、权限控制、日志(容错)
- FAT32:老式文件系统,U 盘常用,最大支持单文件 4GB(这就是为什么大文件没法复制到某些 U 盘)
- exFAT:FAT32 的升级版,跨平台、支持大文件,U 盘/SD 卡常用
- APFS:Apple 文件系统,macOS/iOS 默认,支持快照、加密
- ext4:Linux 主流文件系统
目录树:文件如何被组织
文件系统把文件组织成树形结构:根目录在最顶层,下面是各种文件夹,文件夹里可以再有文件夹,最末端是文件。
Windows 上:
C:\
├── Windows\
│ ├── System32\
│ └── ...
├── Program Files\
│ ├── Google\
│ │ └── Chrome\
│ └── ...
└── Users\
└── 你的用户名\
├── Desktop\
├── Documents\
└── ...
Linux/macOS 上:
/
├── etc/ ← 系统配置文件
├── home/ ← 用户目录(类似 Windows 的 C:\Users\)
│ └── mav/
├── usr/ ← 程序文件
├── var/ ← 日志、临时文件
└── dev/ ← 设备文件(对,在 Linux 里硬盘也是文件)
索引节点(inode):文件的"身份证"
在 Linux/macOS 的 ext4/APFS 文件系统中(NTFS 有类似机制),每个文件对应一个索引节点(inode,Index Node),记录着:
- 文件大小
- 创建/修改时间
- 权限(谁能读、写、执行)
- 指向数据块的指针(文件内容真正存在哪些扇区)
注意:inode 不存储文件名。文件名存在**目录项(Directory Entry)**里,目录项把"文件名"和"inode 编号"关联起来。
这个设计带来一个有趣的特性:同一个 inode 可以有多个文件名(硬链接)。在 Linux 里:
ln 原文件.txt 新名字.txt # 创建硬链接
现在两个名字指向同一份数据。删除其中一个,数据还在,因为还有另一个名字指着同一个 inode。
"删除"文件到底发生了什么
现在可以回答开头的问题了。
当你删除一个文件时,操作系统做的事情是:
- 删除目录项:把"文件名 → inode"的映射删掉
- 标记空间为可用:把这些扇区标记为"空闲",可以被新数据覆盖
但数据本身仍然在磁盘上,只是没有人"指向"它了,等待被新数据覆盖。
这就是为什么:
- 数据恢复软件(如 DiskGenius、Recuva)能在删除后找回文件——只要那些扇区还没被新数据覆盖
- 真正安全地删除文件需要主动覆写数据(用
sdelete、shred等工具),仅仅删除不够 - 格式化硬盘不等于数据消失——快速格式化只是重建文件系统的目录结构,数据还在;完全格式化才会覆写所有扇区
【建议配图】文件删除示意图:
删除前:
目录表:[ "论文.docx" → inode #1024 ]
inode #1024:大小 50KB,数据在扇区 8000-8100
扇区 8000-8100:[实际文件数据 ████████]
删除后(快速删除):
目录表:[ (空) ] ← 目录项已删除
inode #1024:(标记为未使用) ← inode 释放
扇区 8000-8100:[实际文件数据 ████████] ← 数据仍然存在!
文件碎片:为什么硬盘越用越慢
机械硬盘(HDD)时代,有一个经典问题叫文件碎片化(Fragmentation)。
磁盘使用一段时间后,空闲空间变得"零散"——这里有一块、那里有一块,不连续。当系统要存储一个大文件时,找不到足够大的连续空间,就只能把文件切成碎片存在磁盘各处。
这时候,读取这个文件需要磁头在磁盘上来回跳动,大幅降低读取速度。这就是为什么 Windows 要定期"磁盘碎片整理"——整理程序会把碎片重新排列成连续的块。
固态硬盘(SSD)没有这个问题——SSD 访问任何位置的速度几乎相同(没有机械磁头),所以碎片对 SSD 影响极小。不要对 SSD 做碎片整理,频繁写入会磨损闪存颗粒(当然 Windows 11 已经足够聪明,不会对 SSD 做传统碎片整理,而是做"优化")。
日志文件系统:如何防止断电损坏
如果你在写文件时突然断电,会发生什么?
可能写到一半的文件系统元数据(比如 inode、目录项)被破坏,导致文件系统不一致——有些扇区既没被标记为属于文件,也没被标记为空闲,成了"孤儿"。
现代文件系统(NTFS、ext4、APFS 等)用**日志(Journal/Log)**来解决这个问题:
在真正写入数据前,先在一个专门的"日志区"记录"我接下来要做什么"。如果操作中途失败,系统重启时检查日志,可以撤销未完成的操作,恢复一致状态。
这就是为什么你的 Windows 电脑如果强制断电,重启时会有一个"检查磁盘"的过程——它在检查日志,修复可能的不一致。
❌ 常见误区澄清
❌ "格式化就能彻底删除数据" → ✅ 快速格式化只是重建目录结构,数据依然在磁盘上。要出售或报废硬盘,必须做多次覆写(HDD)或加密擦除/厂商安全抹除(SSD)。
❌ "FAT32 是老的,就是坏的,别用" → ✅ FAT32 的主要限制是单文件最大 4GB 和分区最大 2TB,但它的优点是跨平台兼容性最强(Windows、macOS、Linux、嵌入式系统都支持)。对于 U 盘传小文件,FAT32 很合适;需要传大文件用 exFAT。
🔧 动手观察:查看你的硬盘分区和文件系统
Windows: 打开命令提示符(管理员),输入:
diskpart
list disk
list volume
可以看到你的硬盘分区信息,注意"文件系统"一列(NTFS、FAT32 等)和每个分区的大小。
或者右键点击"此电脑"→ 管理 → 磁盘管理,图形化查看分区布局。
macOS: 打开终端,输入:
diskutil list
可以看到所有磁盘和分区,包括文件系统类型(APFS、FAT32 等)。
观察重点:注意你的系统盘(通常是 C 盘或 Macintosh HD)用的是什么文件系统,大小是多少。思考:为什么 U 盘通常用 FAT32 或 exFAT,而不是 NTFS?
✓ 本节要点
- ✓ 文件系统是管理磁盘空间的规则,让操作系统知道哪些扇区属于哪个文件
- ✓ "删除"文件只是删掉目录项,数据仍在磁盘上,等待被覆盖——这是数据恢复软件能工作的原因
- ✓ 文件碎片化会降低机械硬盘速度,但对固态硬盘影响极小
- ✓ 日志文件系统通过预写日志,保证断电后系统可以恢复一致状态
3.4 驱动程序:硬件和软件的翻译官
为什么插上新设备,系统要"安装驱动"?
你买了一块新的声卡,插进电脑,Windows 弹出"正在安装驱动程序"的提示。
为什么不能直接用?
因为操作系统不认识你的声卡。
这个道理很直观:如果你说中文,对方说阿拉伯语,你们需要一个翻译。操作系统是"中文方",硬件是"阿拉伯语方",**驱动程序(Driver)**就是翻译官。
驱动程序是什么
每种硬件设备都有自己的通信协议——发什么指令代表"播放声音",发什么指令代表"调节音量",响应什么格式的数据。这套协议是硬件厂商定义的,不同厂商、不同产品的协议都不一样。
驱动程序是由硬件厂商(或开源社区)开发的软件,作用是:
操作系统发出通用指令 驱动程序翻译 硬件执行
"播放 44100Hz 立体声音频" ──→ 转换成 声卡专属指令 ──→ 声卡发出声音
"显示这帧游戏画面" ──→ 转换成 GPU 专属指令 ──→ 显卡渲染画面
"读取 /dev/sda 的第 100 个扇区" → 转换成 硬盘控制指令 → 硬盘返回数据
驱动程序运行在内核态(第 3.1 节说过的),权限极高。这就是为什么一个写得烂的驱动程序会导致蓝屏(BSOD,Blue Screen of Death)——它在内核里崩溃,没有更高权限的程序来拯救它,整个系统就挂了。
为什么驱动会出问题
你可能遇到过:"换了系统之后声音没了"、"鼠标用着突然卡顿"、"显卡驱动更新之后游戏崩溃"。
这些问题有几种来源:
① 没有驱动 硬件太新,操作系统里没有预置对应的驱动。尤其是在刚装好系统时,部分硬件可能处于"无驱动"状态(设备管理器里显示黄色叹号)。解决方法:去厂商官网下载对应驱动,或更新 Windows Update(微软会通过 Windows Update 推送驱动)。
② 版本不匹配 驱动程序有版本号,操作系统也有版本号。如果操作系统大更新(比如 Windows 10 → Windows 11),部分老驱动可能不再兼容,因为操作系统的内核接口可能变了。
③ 驱动本身有 Bug 驱动程序不是完美的。显卡驱动的代码量可能有数百万行,有 Bug 很正常。这就是为什么显卡厂商(NVIDIA、AMD)会不断推出驱动更新——修 Bug、提升新游戏的性能。
④ 驱动冲突 两个驱动程序同时想控制同一块硬件,或者争用同一个系统资源,就可能发生冲突。这在 Windows 上历史上是个大问题,现在好多了。
通用驱动 vs 专用驱动
操作系统预置了很多通用驱动(Generic Driver),实现了基础功能。比如:
- 插一块陌生的 USB 鼠标,Windows 能用通用 HID(Human Interface Device)驱动让它动起来
- 插一块未知显卡,Windows 能用 Microsoft Basic Display Adapter 让屏幕有画面,但分辨率可能只有 1024×768,且性能很差
安装**专用驱动(Vendor Driver)**后,才能解锁全部功能:
- 鼠标:能用厂商软件配置 DPI、宏按键
- 显卡:能跑游戏、能用 DirectX 12、能开 DLSS
这也解释了为什么刚装完系统,显示器分辨率"不对"——在没有正确显卡驱动的情况下,系统用的是通用显示驱动,无法驱动显卡的全部能力。
驱动签名:安全机制
因为驱动运行在内核态,权限极高,恶意驱动能做的破坏远超普通恶意软件。为此,Windows 引入了**驱动签名(Driver Signing)**机制:
驱动程序必须由微软认证的数字证书签名,才能在 64 位 Windows 上安装。没有签名(或签名无效)的驱动,默认不允许加载。
这就是为什么安装某些老设备的驱动时,会弹出"Windows 无法验证此驱动程序的发布者"的警告。
某些黑客攻击(如 2022 年的 NVIDIA 证书泄露事件)会利用偷来的合法证书给恶意驱动签名,绕过这个保护机制——所以一旦证书泄露,微软会吊销该证书。
Linux 的驱动生态:开源的两面性
Linux 的驱动情况有点特殊,值得单独说一下。
好消息:大量硬件驱动直接集成在 Linux 内核里,插上就能用(尤其是网卡、键鼠、常见 USB 设备)。Linux 内核有数千万行代码,其中很大比例是驱动程序。
坏消息:部分硬件(尤其是 NVIDIA 显卡、部分无线网卡、某些打印机)的 Linux 驱动是闭源的,质量参差不齐,或者根本没有 Linux 驱动。
NVIDIA 的 Linux 驱动一度是 Linux 用户的心病。2022 年,NVIDIA 宣布开放其 GPU 内核驱动模块的源代码,Linux 社区欢呼雀跃——这是一个重要的里程碑。但闭源的 userspace 驱动(如 CUDA)依然存在。
这也是很多 Linux 用户推荐 AMD 显卡的原因:AMD 在 Linux 上用的是完全开源的驱动(amdgpu),由 AMD 官方维护且合并进了内核主线,兼容性和稳定性更好。
macOS 的驱动:紧耦合的优雅
macOS 的驱动情况则完全不同。
苹果对 Mac 的硬件有严格控制——只有特定的芯片、特定的组件才会出现在 Mac 上。苹果自己为这些硬件写驱动,预置在 macOS 里,用户几乎感知不到驱动的存在。
你买了一台 MacBook,开机,所有硬件立刻工作,不需要安装任何驱动。这是因为苹果的软硬件一体化策略:我控制硬件,我控制软件,我来保证两者完美配合。
代价是:如果你想用一块苹果不支持的显卡,几乎没有办法——苹果不提供驱动,第三方也没有权限写内核级驱动。这是 Mac 封闭性的体现。
对于 Apple Silicon(M1/M2/M3/M4 系列),这种一体化更进一步:CPU、GPU、内存、IO 都在同一颗芯片上,驱动层面的优化空间更大,macOS 能把每个硬件模块的性能发挥到极致。
❌ 常见误区澄清
❌ "驱动越新越好,应该一直更新" → ✅ 驱动更新可能引入新 Bug,尤其是显卡驱动。如果目前系统稳定、游戏运行正常,没有必要追着最新版驱动跑。"不坏就别修"是有道理的。遇到特定问题(游戏崩溃、性能倒退)再针对性地更新或回退驱动。
❌ "设备管理器里没有叹号就表示驱动完全没问题" → ✅ 没有叹号说明驱动加载成功,但不代表驱动工作正常。驱动可能加载了但有功能缺失。实际测试(声音能不能播放、显卡能不能渲染 3D)才是最终验证。
🔧 动手观察:查看你的驱动状态
Windows: 右键"此电脑"→ 属性 → 设备管理器(或者在搜索栏搜"设备管理器")。
展开各个分类,观察:
- 有黄色叹号 ⚠️ 的设备:驱动有问题,需要安装/更新
- 右键一个设备 → 属性 → 驱动程序选项卡:可以看到驱动版本、提供商(Microsoft 还是厂商自己的驱动)、安装日期
特别查看:
- 显示适配器:你的显卡用的是什么驱动?如果是"Microsoft Basic Display Adapter"说明没有正确的显卡驱动
- 声音、视频和游戏控制器:你的声卡驱动是否正常
# 命令行查看所有已安装驱动(管理员权限)
driverquery /fo table
macOS: 打开"系统信息"(苹果菜单 → 关于本机 → 更多信息 → 系统报告),在左侧的"软件"分类下找"扩展",可以看到所有加载的内核扩展(kext),包括驱动。
✓ 本节要点
- ✓ 驱动程序是硬件和操作系统之间的"翻译官",把操作系统的通用指令转换成硬件专属指令
- ✓ 驱动运行在内核态,权限极高——写得烂的驱动会导致蓝屏或系统崩溃
- ✓ 通用驱动提供基础功能,专用(厂商)驱动解锁全部性能和特性
- ✓ macOS 通过软硬件一体化几乎消除了驱动问题;Linux 的驱动生态更复杂,取决于硬件厂商的支持力度
3.5 系统调用:应用程序和内核的边界(补充节)
一次"请求"的旅程
你在 Python 里写了一行:
with open("data.csv", "r") as f:
content = f.read()
表面上这就是"打开文件,读取内容"。但在操作系统层面,发生了什么?
这里实际上触发了系统调用(System Call,简称 syscall)。
为什么需要系统调用
我们在 3.1 节说过:应用程序运行在"用户态",权限受限;内核运行在"内核态",权限最高。
用户态的程序不能直接访问硬件(读硬盘、发网络包、申请更多内存……),必须通过一套特定的接口"请求"内核代劳。这套接口就叫系统调用。
这个设计是故意的:
- 安全:如果任何程序都能直接写硬盘,恶意软件就能随意破坏别人的文件
- 隔离:内核统一管理资源,防止程序冲突
- 稳定:内核验证请求的合法性,防止非法访问导致系统崩溃
系统调用的过程(精简版)
当 Python 执行 open("data.csv", "r") 时:
① Python 解释器调用 C 标准库的 fopen()
② fopen() 内部调用操作系统提供的 open() 系统调用
③ CPU 执行特殊指令(x86 上是 syscall 指令)切换到内核态
④ 内核接管,检查:文件存在吗?你有权限读吗?
⑤ 内核通过文件系统找到文件,通过硬盘驱动读取数据
⑥ 数据放入内核缓冲区,复制到用户态内存
⑦ 内核返回,CPU 切回用户态,控制权交回 Python
⑧ Python 的 f.read() 拿到文件内容
整个过程对你透明,但每次"用户态 → 内核态 → 用户态"的切换是有开销的。这就是为什么高性能程序(比如数据库、游戏服务器)会想办法减少系统调用次数——比如一次性读大块数据,而不是一个字节一个字节地读。
Linux 上的系统调用一瞥
Linux 有几百个系统调用,按功能分类:
| 类别 | 代表系统调用 | 说明 |
|---|---|---|
| 文件 I/O | open, read, write, close |
操作文件 |
| 进程 | fork, exec, wait, exit |
创建/管理进程 |
| 内存 | mmap, brk |
申请/释放内存 |
| 网络 | socket, connect, send, recv |
网络通信 |
| 信号 | kill, signal |
进程间信号 |
| 时间 | gettimeofday, nanosleep |
时间相关 |
🔧 动手:用 strace 看系统调用(Linux/macOS)
如果你有 Linux 环境(比如 WSL 或 SSH 到服务器),可以用 strace 命令追踪一个程序的系统调用:
# 追踪 ls 命令的系统调用
strace ls
# 只显示系统调用的统计信息
strace -c ls
# 追踪文件操作相关的系统调用
strace -e trace=file ls
输出会很多,但你能看到 openat(打开文件)、read(读取)、write(写输出)等系统调用,以及每次调用的参数和返回值。
这是真正看到"底层发生了什么"的最直接方式。
macOS 上对应的工具是 dtruss(需要关闭 SIP)或 ktrace。
✓ 本节要点
- ✓ 系统调用是用户态程序请求内核服务的唯一合法通道
- ✓ 每次系统调用都涉及用户态/内核态切换,有性能开销
- ✓ 所有 I/O 操作(文件、网络、设备)最终都通过系统调用完成
- ✓ 高性能程序的优化策略之一,就是减少不必要的系统调用次数
3.6 中断:硬件怎么"打断"CPU
键盘按下去,CPU 怎么知道?
你按下键盘上的 "A",屏幕上出现了 "a"。
这个过程看起来理所当然,但仔细想想有个问题:CPU 在一直执行代码,它怎么知道你按了键?它总不能一直"查"键盘有没有按键吧?
答案是:它不用查。键盘会主动通知 CPU。
这个机制叫做中断(Interrupt)。
什么是中断
中断是硬件设备向 CPU 发出的一个信号,意思是:"我有事要汇报,请暂停你正在做的事,先来处理我。"
CPU 正在执行进程 A 的代码
↓
键盘发出中断信号(IRQ,中断请求)
↓
CPU 保存当前状态(寄存器值、程序计数器)
↓
CPU 跳转到对应的"中断处理程序(Interrupt Handler)"
↓
中断处理程序读取键盘缓冲区,获取按键信息,传给操作系统
↓
CPU 恢复之前的状态,继续执行进程 A
整个过程发生在微秒级别,进程 A 几乎感知不到被打断了。
中断的分类
硬件中断:由硬件设备触发
- 键盘按键 → 键盘控制器发中断
- 网卡收到数据包 → 网卡发中断
- 硬盘读取完成 → 硬盘控制器发中断
- 系统定时器(每隔一定时间) → 定时器发中断(这是调度器工作的基础!)
软件中断(也叫异常/陷阱):由软件或 CPU 本身触发
- 程序执行了系统调用 → CPU 触发软件中断
- 程序访问了无效内存地址 → CPU 触发"段错误"异常(Segmentation Fault)
- 程序除以零 → CPU 触发算术异常
定时器中断:调度器的"心跳"
有一个特别重要的中断值得单独讲:定时器中断(Timer Interrupt)。
计算机里有一个硬件定时器(在现代 PC 上是 HPET 或 APIC 定时器),它会以固定频率(通常是每秒 100 到 1000 次)发出中断。
每次定时器中断触发,操作系统调度器就会运行一次,决定:
- 当前进程的时间片用完了吗?
- 要不要切换到另一个进程?
- 有没有优先级更高的进程需要抢占?
调度器本质上是由定时器中断驱动的。没有这个定时器,调度器永远没机会运行,某个进程霸占 CPU 就没人能制止它。
这也解释了 Linux 内核的一个参数 CONFIG_HZ:它决定定时器中断的频率,比如 HZ=250 表示每秒 250 次定时器中断,每次调度器都有机会运行。
中断和系统调用的区别
这两个概念容易混淆,区分一下:
| 中断 | 系统调用 | |
|---|---|---|
| 发起方 | 硬件(或 CPU 异常) | 用户程序主动请求 |
| 时机 | 随时,异步 | 程序执行到特定指令时 |
| 目的 | 通知 CPU 某事件发生 | 请求内核提供服务 |
| 举例 | 网卡收到数据包、键盘按键 | open 文件、malloc 内存 |
简单说:中断是硬件找操作系统,系统调用是程序找操作系统。
✓ 本节要点
- ✓ 中断是硬件通知 CPU"有事发生"的机制,使 CPU 无需轮询硬件状态
- ✓ 定时器中断是操作系统调度器的心跳,保证没有进程能无限霸占 CPU
- ✓ 中断(硬件主动)和系统调用(程序主动)是应用程序/硬件与内核交互的两种方式
- ✓ 中断处理要尽可能快,处理时间过长会影响系统响应性
章节综合:把进程、文件、驱动串起来
我们来做一个完整的场景推演,把本章所有概念串联起来。
场景:你在 Windows 上打开一个 MP3 文件,用 Foobar2000 播放。
第一步:你双击 MP3 文件图标
Windows 的 Shell(Explorer.exe,一个进程)检测到你的双击操作。操作系统查找 .mp3 扩展名关联的程序,找到 Foobar2000。
第二步:操作系统创建 Foobar2000 进程
内核为 Foobar2000 分配一块独立内存空间,把 foobar2000.exe 从磁盘(通过文件系统 → NTFS 驱动 → 硬盘驱动)载入内存。进程创建完成,进入就绪状态。
第三步:调度器把 CPU 给 Foobar2000
Foobar2000 进程开始执行。它发起系统调用,请求操作系统打开那个 MP3 文件。操作系统通过文件系统找到对应的 inode,找到数据所在的磁盘扇区,通过硬盘驱动程序读取数据,把 MP3 的二进制数据放进内存。
第四步:Foobar2000 解码音频
Foobar2000 调用解码库,把 MP3 格式的压缩音频数据,解码成原始 PCM 波形数据(一堆数字,表示每个时刻的振幅)。
第五步:把音频传给声卡
Foobar2000 调用 Windows 音频 API(WASAPI 或 DirectSound),把 PCM 数据传给操作系统的音频子系统。音频子系统通过声卡驱动程序,将数据写入声卡缓冲区,声卡把数字信号转成模拟信号,耳机/音箱发出声音。
整个过程涉及了:
- 进程管理(创建 Foobar2000 进程)
- 调度器(给进程分配 CPU 时间)
- 文件系统(找到 MP3 文件)
- 驱动程序(硬盘驱动读数据,声卡驱动输出音频)
- 系统调用(应用程序请求操作系统服务)
这就是为什么操作系统被称为"看不见的管家"——每一次文件操作、每一个音符、每一次鼠标点击,背后都是操作系统在默默协调。
3.7 权限与安全:操作系统的"警卫"
为什么有些程序要"管理员权限"?
你在 Windows 上安装软件,弹出"是否允许此应用更改设备?"的 UAC(用户账户控制)提示。你在 Linux 上跑某个命令,系统说"Permission denied"。你在 macOS 上第一次让某个 App 访问相机,弹出授权提示。
这些都是操作系统的权限控制系统在工作。
用户和权限的基础概念
Unix/Linux/macOS 的权限模型
Unix 系的操作系统(Linux、macOS 都属于这一脉)有一套经典的权限模型:
每个文件/目录都有三组权限:
- 所有者(Owner):文件的创建者
- 所属组(Group):一组用户
- 其他人(Others):所有其他用户
每组又有三种权限:
- 读(r,Read):可以查看内容
- 写(w,Write):可以修改内容
- 执行(x,Execute):可以运行(文件)或进入(目录)
# ls -l 的输出示例:
-rwxr-xr-x 1 mav staff 4096 Mar 28 10:00 my_script.sh
# ↑ ↑ ↑ ↑
# 权限 所有者 所属组
#
# 权限字段解读:-rwxr-xr-x
# 第1位 - :普通文件(d 是目录,l 是符号链接)
# 第2-4位 rwx:所有者(mav)可读、可写、可执行
# 第5-7位 r-x:所属组(staff)可读、不可写、可执行
# 第8-10位 r-x:其他人可读、不可写、可执行
超级用户 root
在 Unix 系统里,有一个特殊用户叫 root,权限不受任何限制——可以读任何文件、写任何文件、杀任何进程。
root 权限非常危险,日常使用不应该以 root 登录。这就是为什么 Linux 上很多操作要 sudo(Substitute User DO)临时提权,macOS/Ubuntu 默认禁止直接以 root 登录。
Windows 的权限模型
Windows 的权限系统更复杂,基于 ACL(访问控制列表)。每个文件/目录可以给特定用户或用户组设置精细的权限。
Windows 的 UAC(用户账户控制)则是另一层保护:即使你以管理员账户登录,程序默认也以"标准用户"权限运行。只有明确需要管理员权限时(安装软件、修改系统设置),才会弹出 UAC 提示要求确认。
这个设计来自一个教训:Windows XP 时代,用户默认以管理员运行,恶意软件可以轻易感染系统。Vista 引入 UAC 后,安全性大幅提升(尽管当时被嫌烦)。
沙箱:更严格的隔离
进程之间已经有了内存隔离,但操作系统的权限系统是"文件/资源级"的,粒度有限。
现代操作系统还提供了**沙箱(Sandbox)**机制:把一个程序限制在一个更小的权限范围内,即使它被黑了,也无法影响系统其他部分。
- 浏览器沙箱:Chrome 的渲染进程(负责渲染网页的进程)被放在沙箱里,即使网页上的恶意代码利用了渲染引擎的漏洞,也很难突破沙箱跑出来
- iOS/Android 应用沙箱:每个 App 只能访问自己的数据目录,要访问联系人、相机等需要显式申请权限
- macOS App Sandbox:App Store 上架的应用必须声明需要什么权限,用户可以在隐私设置里管理
❌ 常见误区澄清
❌ "以管理员运行所有程序更方便" → ✅ 管理员权限意味着程序可以做任何事,包括破坏系统或安装恶意软件。普通权限够用时就不要提权——这是"最小权限原则"(Principle of Least Privilege)。
❌ "chmod 777 能解决所有权限问题"(Linux 用户)
→ ✅ chmod 777 给所有人读/写/执行权限,这很危险,尤其是对 Web 服务器的文件。正确做法是找到真正需要的最小权限,而不是无脑 777。
🔧 动手:查看文件权限
Linux/macOS:
# 查看当前目录的文件权限
ls -la
# 查看自己是谁
whoami
id
# 查看一个文件的所有者和权限
stat 文件名
# 创建一个文件,修改权限,体验权限控制
touch test.txt # 创建文件
ls -la test.txt # 查看默认权限(通常是 -rw-r--r--)
chmod 000 test.txt # 移除所有权限
cat test.txt # 尝试读取——Permission denied
chmod 644 test.txt # 恢复权限(所有者读写,其他人只读)
cat test.txt # 现在可以读了
Windows: 右键任意文件 → 属性 → 安全选项卡,可以看到每个用户/组对这个文件的具体权限(完全控制、修改、读取等)。
✓ 本节要点
- ✓ 操作系统通过用户/组和读写执行权限控制谁能访问什么资源
- ✓ root/Administrator 是超级用户,日常应避免以超级用户身份运行程序(最小权限原则)
- ✓ UAC(Windows)和 sudo(Linux)是提权保护机制,防止程序在无感知情况下提升权限
- ✓ 沙箱进一步限制进程的权限范围,即使程序被攻陷也无法影响系统其他部分
3.8 操作系统的启动:从按下电源键到桌面
那 30 秒里发生了什么
按下电源键,30 秒后桌面出现了。
这 30 秒对于很多人来说是个黑盒。让我们拆开看看。
启动流程全景
现代 PC 的启动过程大致分这几个阶段:
按下电源键
↓
① 上电自检(POST)
↓
② 固件(BIOS/UEFI)初始化
↓
③ 引导加载程序(Bootloader)
↓
④ 操作系统内核加载
↓
⑤ 用户空间初始化
↓
登录界面 / 桌面
第一步:上电自检(POST,Power-On Self Test)
你按下电源键,主板的固件(烧录在主板上的芯片里)首先运行。
POST 会检查:CPU 能用吗?内存能用吗?有没有显卡?基本硬件是否正常?
如果有问题,你会听到"哔哔"声(哔声代码,每种故障对应不同的声音模式),或者屏幕上出现错误信息。现代电脑通常 POST 非常快,你几乎感知不到。
第二步:BIOS/UEFI 初始化
**BIOS(Basic Input/Output System)**是老一代的固件标准,1970 年代就有了。 **UEFI(Unified Extensible Firmware Interface)**是 BIOS 的现代替代,2000 年代逐渐普及,现在几乎所有新电脑都用 UEFI。
固件的主要工作:
- 初始化所有硬件(设置内存时序、检测 CPU 型号……)
- 找到"可以启动操作系统的设备"(硬盘、U 盘、网络……)
- 把控制权交给那个设备上的引导程序
UEFI 比 BIOS 强在哪里?
- 支持超过 2TB 的硬盘(BIOS 时代有 2TB 限制)
- 支持 GPT 分区表(BIOS 只支持 MBR)
- 有图形界面,支持鼠标操作
- 启动更快(直接加载 EFI 程序,不需要通过 MBR 这个中转)
- 支持安全启动(Secure Boot)——只允许加载经过签名的引导程序
Secure Boot 是一个安全特性:UEFI 固件只加载经过数字签名的引导程序,防止恶意软件在操作系统加载前就植入。这就是为什么在有些电脑上安装 Linux 时,需要先在 UEFI 里关掉 Secure Boot(或者用支持 Secure Boot 的 Linux 发行版,比如 Ubuntu)。
第三步:引导加载程序(Bootloader)
固件找到启动设备后,加载并运行引导加载程序。
Windows 的引导加载程序:Windows Boot Manager(bootmgr),存在 EFI 系统分区里
Linux 的主流引导加载程序:GRUB(GRand Unified Bootloader)
macOS:苹果的专属引导程序,在 Apple Silicon 上集成在 iBoot 里
引导加载程序的任务:
- 显示操作系统选择菜单(如果你装了双系统,就是在这里选"Windows 还是 Ubuntu")
- 把操作系统内核从磁盘加载到内存
- 把控制权交给内核
第四步:内核初始化
内核拿到控制权后,开始进行一系列初始化:
- 初始化内存管理(建立页表)
- 加载核心驱动程序(让更多硬件可用)
- 挂载根文件系统(
/或C:\) - 启动第一个用户空间进程
Linux 上,第一个用户空间进程是 systemd(或老系统上的 init),PID(进程 ID)为 1。它是所有其他进程的"父亲",负责按顺序启动系统服务。
Windows 上对应的是 smss.exe(Session Manager Subsystem),然后是 wininit.exe,再启动各种 Windows 服务。
第五步:用户空间初始化
systemd(Linux)或 Windows 服务管理器启动各种服务:
- 网络服务
- 音频服务
- 显示管理器(登录界面)
- 各种后台守护进程(daemon)
最终,显示管理器启动,桌面环境(GNOME、KDE、Windows Shell……)加载,你看到了熟悉的桌面。
这整个过程,现代 SSD 加持下可以在 10 秒内完成。而在机械硬盘时代,同样的过程可能要 60 秒——因为内核和系统文件分散在磁盘各处,机械磁头需要大量寻道时间。
【建议配图】启动流程时序图:
时间轴(以 SSD 系统为例,约 10-15 秒):
0s 按下电源键
0-1s POST 完成
1-2s UEFI 初始化、寻找启动设备
2-4s Windows Boot Manager 加载内核
4-8s Windows 内核初始化、驱动加载
8-12s 服务启动(网络、音频、Shell……)
12s 登录界面出现
❌ 常见误区澄清
❌ "开机密码能阻止别人读取我的硬盘数据" → ✅ 开机密码(Windows 登录密码)只是阻止别人登录操作系统,不能保护硬盘数据。把硬盘拔出来接到另一台电脑,或者用 U 盘引导 Linux,就能直接访问硬盘上的所有文件(除非开了 BitLocker 全盘加密)。要真正保护数据,必须用全盘加密(Windows BitLocker、macOS FileVault)。
❌ "快速启动/休眠和关机是一样的" → ✅ Windows 的"快速启动"(默认开启)实际上是混合休眠:关机时把内核状态保存到磁盘(hiberfil.sys),下次开机直接恢复,跳过内核初始化阶段,所以快。但这意味着内核实际上没有被重新加载,有时候驱动更新需要"完全关机"(按 Shift + 关机,或者先禁用快速启动)才能生效。
🔧 动手:查看启动时间分析
Windows:
# 查看最近一次开机的启动事件日志
eventvwr.msc
# → Windows 日志 → 系统 → 筛选"事件 ID 12"(系统启动)和"事件 ID 6005"(Event Log 服务启动)
# 或者使用 Performance Monitor 分析启动性能
perfmon /rel
也可以直接搜索"启动时间",Windows 10/11 的任务管理器 → 性能 → 右下角有"正常运行时间"。
Linux:
# 分析 systemd 启动时间
systemd-analyze
# 查看每个服务的启动时间
systemd-analyze blame
# 生成启动过程的 SVG 时序图
systemd-analyze plot > boot.svg
# 然后用浏览器打开 boot.svg,直观看到哪个服务拖慢了启动
macOS:
# 查看上次启动时间
last reboot | head -5
# 通过 Console.app(控制台)查看启动日志
# 过滤 "kernel" 相关条目可以看到内核初始化序列
✓ 本节要点
- ✓ 启动过程分为 POST → UEFI → Bootloader → 内核 → 用户空间五个阶段
- ✓ UEFI 是 BIOS 的现代替代,支持更大硬盘、更快启动和安全启动
- ✓ 操作系统内核是第一个被加载的"正式软件",随后它初始化驱动和服务
- ✓ 开机密码不保护数据,全盘加密才能防止物理接触后的数据泄露
深入一点:操作系统的内存管理(补充阅读)
这一小节是补充内容,稍微深入,可选阅读。
虚拟内存:内存"变大"的魔法
在第一章,我们提到了虚拟内存(Virtual Memory)。现在可以更好地理解它了。
每个进程"看到"的内存地址,不是真实的物理内存地址,而是虚拟地址。操作系统(通过 CPU 中的内存管理单元,MMU)负责把虚拟地址翻译成物理地址。
【建议配图】虚拟地址到物理地址的映射:
进程 A 的虚拟地址空间: 物理内存:
0x00000000 ──────────────→ 0x12340000 (进程 A 的代码)
0x00001000 ──────────────→ 0x56780000 (进程 A 的数据)
...
进程 B 的虚拟地址空间:
0x00000000 ──────────────→ 0x89AB0000 (进程 B 的代码,和 A 在不同物理位置)
...
两个进程都"以为"自己从地址 0 开始,互不干扰。这就是内存隔离的实现原理。
当物理内存不够用时,操作系统会把暂时用不到的内存页交换(Swap)到硬盘上,腾出物理内存给当前需要的进程。被换出到硬盘的部分,叫做页面文件(Windows)或Swap 分区(Linux)。
代价是:硬盘比内存慢几千倍,大量 Swap 会让系统变得极其缓慢——你可能听说过"内存不够,电脑卡死",本质就是 Swap 到硬盘,然后 CPU 大量时间在等硬盘。
这就是为什么内存容量很重要:内存越大,越不需要 Swap,系统越流畅。
内存分配:malloc 背后的故事
当你的程序需要内存(比如 Python 里创建一个 numpy 数组),会调用内存分配函数(C 里是 malloc,Python/C++ 有更高层的封装)。
这个函数最终会发出 mmap 或 brk 系统调用,让操作系统在这个进程的虚拟地址空间里划出一块区域。
注意:操作系统给的是虚拟内存,不一定立刻对应真实的物理内存。只有当你真正去读写那块内存时,操作系统才会为你分配物理内存页(这叫按需分页,Demand Paging)。
这就是为什么有时候你分配了 4GB 内存,但任务管理器显示程序的实际内存占用只有 500MB——因为程序还没访问那 3.5GB,操作系统还没真正给。
3.9 实战:操作系统的日常维护与调优
这一节是实用向的,帮你把本章的理论和日常使用联系起来。
理解为什么电脑"变慢"了
用了一两年的电脑,感觉比刚买时慢。这是真的吗?为什么?
根据本章的知识,可以从几个角度分析:
① 后台进程越来越多
每次安装软件,都可能顺带安装了一些"开机自启动"的后台程序(更新助手、云盘同步、输入法助手……)。这些程序常驻后台,占用内存,和其他进程竞争 CPU。
诊断方法:任务管理器 → 启动应用,看有哪些开机自启动项,禁用不需要的。
② 内存不够,频繁 Swap
随着使用习惯改变,你同时打开的程序越来越多。如果物理内存不足,操作系统开始把内存数据交换到硬盘,速度断崖式下降。
诊断方法:任务管理器 → 性能 → 内存,看"已提交"是否远超物理内存,或者看磁盘利用率是否异常高(说明在 Swap)。
③ 磁盘空间不足(机械硬盘尤其明显)
机械硬盘的碎片化,以及磁盘将满时文件系统的工作效率下降,都会影响性能。
SSD 则有另一个问题:接近写满时,NAND 闪存的写入放大效应加剧,性能下降。建议 SSD 保留 10-15% 的空闲空间。
④ 软件本身越来越重
Chrome 2015 年用 200MB 内存,2024 年用 1GB 不罕见。软件功能增加了,资源占用也增加了。电脑没变慢,是软件变重了。
这种现象有个戏谑的名字叫 Wirth's Law(沃斯定律):"软件的速度每隔 18 个月就会慢一半"——和摩尔定律(硬件性能翻倍)反着来。
内存使用诊断:一次完整的分析
打开任务管理器,切到"内存"性能图,认识这几个数字:
总计:16.0 GB ← 你安装的物理内存
使用中:8.2 GB ← 正在被进程使用的内存(代码+数据)
可用:5.1 GB ← 操作系统随时可以分配的内存
已提交:12.4 / 22.0 GB ← 已分配的虚拟内存 / 最大可用虚拟内存
已缓存:2.7 GB ← 系统用来缓存磁盘数据的内存(可以被回收)
"已提交"超过物理内存:说明操作系统开始使用 Swap(页面文件),性能会下降 "可用"很低(低于 1GB):内存可能不够,关一些不用的程序 "已缓存"占很多:这是正常的!操作系统会把闲置内存用来缓存磁盘数据,加速文件访问。"空余内存是浪费的内存"——这些缓存随时可以被回收
进程管理:找到消耗资源的罪魁祸首
任务管理器使用技巧:
① 按 CPU 排序:找到 CPU 占用高的进程
- 正常情况下大部分进程应该是 0%
- 如果某个进程长时间 CPU 100%,说明它在死循环或者处理大量数据
② 按内存排序:找到内存占用大的进程
- Chrome 通常排前几名(每个标签一个进程)
- "系统"进程内存高可能是系统缓存(正常)
③ 右键进程 → "转到文件位置"
- 可以查看这个进程对应的可执行文件在哪里
- 帮助判断是否是可疑的后台进程
④ 右键进程 → "结束任务"
- 强制终止进程(相当于给进程发 SIGKILL 信号)
- 注意:结束任务会丢失该进程未保存的数据
Linux 下的进程管理工具
如果你用 Linux(或者通过 SSH 管理服务器),有几个必备工具:
# top:实时显示进程列表(类似任务管理器)
top
# 常用快捷键:q 退出,k 杀进程,M 按内存排序,P 按 CPU 排序
# htop:top 的增强版(需要安装:sudo apt install htop)
htop
# 更好看,支持鼠标,可以直接点击排序列
# ps:列出进程快照
ps aux # 显示所有进程
ps aux | grep chrome # 过滤特定进程
# kill:发送信号给进程
kill 1234 # 给 PID 1234 的进程发 SIGTERM(优雅终止)
kill -9 1234 # 发 SIGKILL(强制杀死,进程无法捕获)
killall chrome # 按名字杀所有同名进程
# nice/renice:调整进程优先级
nice -n 10 ./heavy_script.sh # 以低优先级运行
renice -n 5 -p 1234 # 调整已运行进程的优先级
在 Robogame 项目的嵌入式开发里,你虽然用的是 ESP32(裸机或 FreeRTOS),但这些 Linux 进程管理知识在 Raspberry Pi 或 Linux 服务器上同样适用。
磁盘健康监测
硬盘是会"死"的,尤其是机械硬盘。及时发现硬盘问题,可以在数据丢失前备份。
SMART(Self-Monitoring, Analysis and Reporting Technology) 是硬盘自带的健康监测系统,记录了各种硬件指标(读写错误次数、重分配扇区数、通电时间等)。
# Linux:查看硬盘 SMART 信息(需要安装 smartmontools)
sudo smartctl -a /dev/sda
# 关键指标:
# Reallocated_Sector_Ct:重分配扇区数(坏块被备用扇区替换)
# → 如果这个数字在增加,硬盘正在损坏
# Pending_Sector_Count:等待重分配的扇区数
# → 大于 0 说明有读取不稳定的扇区
# Power_On_Hours:总通电时间(评估使用寿命)
Windows:可以用 CrystalDiskInfo(免费软件,日本开发者出品,非常可靠)查看硬盘 SMART 信息,界面直观,绿色是健康,黄色/红色要警惕。
SSD 特有指标:
- Wear Leveling Count / Media Wearout Indicator:SSD 写入磨损量。100 表示全新,趋近 0 表示寿命快到了
- Total Bytes Written(TBW):SSD 总写入量。SSD 有写入寿命,厂商会给出保修的 TBW 数值
✓ 本节要点
- ✓ 电脑"变慢"的常见原因:后台进程增多、内存 Swap、软件越来越重——可以通过任务管理器针对性排查
- ✓ 内存"已缓存"部分是正常优化,不是内存泄露;真正的问题是"已提交"超过物理内存
- ✓ Linux 的
top/htop/ps/kill是服务器运维的基础工具 - ✓ SMART 是硬盘自带的健康监测,用 CrystalDiskInfo 定期检查可以及早发现硬盘故障
操作系统家族小史(拓展阅读)
如果你对操作系统的发展历史感兴趣,这里有一个极简版:
1960s:大型机时代,"操作系统"主要是批处理系统,一次只能运行一个程序。
1969-1973:Unix 诞生(AT&T 贝尔实验室,Ken Thompson & Dennis Ritchie)。Unix 的多任务、多用户、树形文件系统等设计奠定了现代 OS 的基础。C 语言最初就是为了重写 Unix 而发明的。
1981:MS-DOS 发布(微软为 IBM PC 开发)。单任务,命令行,是 Windows 的前身。
1984:Mac OS 1.0 发布,第一个商业成功的图形用户界面操作系统(图形界面概念来自施乐 PARC 研究院)。
1991:Linus Torvalds 发布 Linux 内核 0.01,一个芬兰大学生的课余项目,后来成为服务器领域和 Android 的基石。
2001:Mac OS X 发布,苹果重新设计的 Unix-based 操作系统,基于 BSD(另一个 Unix 分支)。Windows XP 同年发布。
2007:iPhone 发布,iOS(基于 Mac OS X)让移动操作系统进入主流。Android 则基于 Linux 内核。
2020至今:Apple Silicon 的推出,重新定义了桌面操作系统和硬件的关系。
章节结尾:联系与展望
本章与前后章节的联系
上一章我们讲了 CPU 和 GPU 的计算能力。这一章告诉了你:这些计算能力是如何被操作系统协调分配的——进程调度器决定每颗 CPU 核心在什么时候跑什么任务;内存管理器决定 GPU 和 CPU 如何共享内存(在 Apple Silicon 上这一点尤为明显)。
下一章我们会看到:主板、芯片组是如何把 CPU、内存、存储、GPU、网卡这些部件物理连接起来的,以及 Apple 的 SoC 设计如何把本章讲的很多概念重新整合。
第一章遗留的问题:我们提过"虚拟内存",这章终于解释清楚了——虚拟内存是操作系统的内存管理机制,不是"额外的物理内存",而是把磁盘空间借用为内存的代偿方案,性能代价高昂。
扩展资源
如果你想更深入地了解操作系统,这里有几个真实存在的资源:
视频推荐:
🎬 Computerphile: "Processes vs Threads"(YouTube,英文) https://www.youtube.com/watch?v=exbKr6fnoUw 20 分钟,清楚地解释了进程和线程的区别,有可视化演示 ⭐ 入门
🎬 3Blue1Brown 风格的内存可视化 "How Computer Memory Works"(YouTube) 搜索:
"how computer memory works" site:youtube.com,推荐 Fireship 或 CS Dojo 的版本 ⭐ 入门
文章/书籍推荐:
📖 《操作系统导论》(OSTEP,Operating Systems: Three Easy Pieces) 免费在线阅读:https://pages.cs.wisc.edu/~remzi/OSTEP/ 这是 CS 专业操作系统课程的经典教材,写得极其清晰有趣,中文翻译版也有 ⭐⭐ 进阶(大一下学期或暑假看比较合适)
📖 "How Linux Works" (Brian Ward) 覆盖了 Linux 内核、进程、文件系统、驱动的底层细节,实用性很强 ⭐⭐⭐ 深入
🌐 OSDev Wiki: https://wiki.osdev.org 想自己写一个简单操作系统?这里是起点。不夸张——有人大一就能写出一个能引导启动的 mini OS。 ⭐⭐⭐ 深入(强烈推荐感兴趣的同学探索)
【下章预告】现在你理解了计算机里"管家"的工作——调度进程、管理文件、翻译驱动。但这些部件是如何被物理连接在一起的?主板上那些插槽、芯片组、总线是干什么的?为什么 Apple M 系列芯片一发布就让 PC 厂商紧张?下一章,我们把拼图的最后几块补上。
本章写作时间:2024 年末。涉及的产品价格和参数如有变化,请以当时市场价格为准。