操作系统全景概览
什么是操作系统
操作系统(Operating System, OS)是管理计算机硬件与软件资源的系统软件,它是用户应用程序和底层硬件之间的桥梁。
用一个比喻来理解:如果把计算机比作一家酒店,那么操作系统就是酒店的管理层——它负责分配房间(内存管理)、安排前台接待客人的顺序(进程调度)、管理仓库物资(文件系统)、协调各部门沟通(进程间通信)。客人(应用程序)不需要直接去和水电工(硬件)打交道,只需要找前台(系统调用)提需求即可。
操作系统的四大核心职责
| 职责 | 管理对象 | 核心问题 | 类比 |
|---|---|---|---|
| 进程管理 | CPU 时间 | 多个程序如何共享一个 CPU? | 安排员工轮班 |
| 内存管理 | 物理内存 | 如何让每个程序以为自己独占内存? | 分配酒店房间 |
| 文件系统 | 磁盘存储 | 数据如何有序地存储和检索? | 图书馆的分类编目 |
| I/O 管理 | 外设设备 | 如何高效地与键盘、磁盘、网卡交互? | 酒店的后勤调度 |
这四大职责是操作系统的骨架,后续文章将逐一深入讲解。
内核:操作系统的核心
操作系统中最关键的部分是内核(Kernel),它直接管理硬件资源,运行在 CPU 的最高特权级别。
内核架构的两种流派
┌──────────────────────────────────────────────┐
│ 宏内核 (Monolithic Kernel) │
│ │
│ ┌──────────────────────────────────────────┐ │
│ │ 内核空间 │ │
│ │ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ │ │
│ │ │进程管理│ │内存管理│ │文件系统│ │设备驱动│ │ │
│ │ └──────┘ └──────┘ └──────┘ └──────┘ │ │
│ │ 所有功能都在内核态运行,性能高 │ │
│ └──────────────────────────────────────────┘ │
│ ┌──────────────────────────────────────────┐ │
│ │ 用户空间:应用程序 │ │
│ └──────────────────────────────────────────┘ │
│ 代表:Linux、Unix │
└──────────────────────────────────────────────┘
┌──────────────────────────────────────────────┐
│ 微内核 (Microkernel) │
│ │
│ ┌──────────────────────────────────────────┐ │
│ │ 内核空间(极简) │ │
│ │ ┌──────────┐ ┌──────────┐ │ │
│ │ │ 进程调度 │ │ IPC 通信 │ │ │
│ │ └──────────┘ └──────────┘ │ │
│ └──────────────────────────────────────────┘ │
│ ┌──────────────────────────────────────────┐ │
│ │ 用户空间 │ │
│ │ ┌──────┐ ┌──────┐ ┌──────┐ │ │
│ │ │文件系统│ │设备驱动│ │网络协议│ │ │
│ │ └──────┘ └──────┘ └──────┘ │ │
│ │ 大部分功能在用户态运行,稳定性高 │ │
│ └──────────────────────────────────────────┘ │
│ 代表:Minix、QNX、鸿蒙(HarmonyOS) │
└──────────────────────────────────────────────┘
| 特性 | 宏内核 | 微内核 |
|---|---|---|
| 内核大小 | 大,包含所有功能 | 小,仅保留最核心功能 |
| 性能 | 高(函数调用) | 较低(需要 IPC) |
| 稳定性 | 一个模块崩溃可能导致整个系统崩溃 | 模块崩溃不影响内核 |
| 可维护性 | 维护困难 | 易于维护和扩展 |
| 代表系统 | Linux、Windows(混合) | Minix、QNX、鸿蒙 |
Linux 采用宏内核架构,但通过**可加载内核模块(LKM)**机制引入了微内核的灵活性——驱动程序可以在运行时动态加载和卸载,无需重新编译内核。
用户态与内核态
操作系统将 CPU 的运行状态分为两个级别:
- 内核态(Kernel Mode):拥有最高权限,可以执行所有 CPU 指令、直接访问硬件和所有内存地址
- 用户态(User Mode):权限受限,只能执行安全的指令子集,不能直接访问硬件
用户态 内核态
┌─────────────┐ ┌─────────────┐
│ 应用程序 │ ── 系统调用 ──▶ │ 内核代码 │
│ (受限权限) │ ◀── 返回结果 ── │ (完全权限) │
└─────────────┘ └─────────────┘
Ring 3 Ring 0
│ │
│ 不能直接操作硬件 │ 可以操作一切
│ 不能访问内核内存 │
▼ ▼
为什么需要这种划分?
如果所有程序都能直接操作硬件,那么一个有 Bug 的程序就可能写坏磁盘数据、覆盖其他程序的内存,甚至让整个系统崩溃。用户态与内核态的划分,本质上是一种安全隔离机制。
从用户态到内核态的三种途径
- 系统调用(System Call):应用程序主动请求内核服务,如
read()、write()、fork() - 异常(Exception):程序运行出错触发,如除零错误、缺页异常
- 中断(Interrupt):外部硬件触发,如键盘输入、网络数据到达、定时器到期
用户态与内核态的深入讲解见
02-Linux基础/01-user-kernel-mode.md。
系统调用:用户程序与内核的接口
系统调用(System Call,简称 syscall)是应用程序请求内核服务的唯一正规途径。
应用程序 C 库 内核
│ │ │
│ printf() │ │
│ ──────────────▶│ │
│ │ write() 系统调用│
│ │ ──────────────▶│
│ │ │ 执行写操作
│ │ 返回结果 │
│ │ ◀──────────────│
│ printf 返回 │ │
│ ◀──────────────│ │
常见系统调用分类
| 类别 | 常见调用 | 作用 |
|---|---|---|
| 进程控制 | fork() exec() wait() exit() |
创建/执行/等待/退出进程 |
| 文件操作 | open() read() write() close() |
打开/读/写/关闭文件 |
| 内存管理 | mmap() brk() munmap() |
映射/分配/释放内存 |
| 网络通信 | socket() bind() listen() accept() |
创建/绑定/监听/接受连接 |
| 设备 I/O | ioctl() poll() select() |
设备控制/I/O 多路复用 |
系统调用的开销
每次系统调用都需要从用户态切换到内核态,涉及:
- 保存用户态上下文(寄存器、程序计数器)
- 切换到内核栈
- 执行内核代码
- 恢复用户态上下文并返回
这个过程比普通函数调用慢得多(通常慢几十到几百倍),因此高性能程序会尽量减少系统调用次数。例如,printf() 会先将数据写入用户态缓冲区,等缓冲区满了再一次性调用 write() 系统调用。
操作系统知识全景地图
下面这张地图展示了操作系统的核心知识脉络,也是本系列文章的组织结构:
操作系统
│
┌────────┬───────┼───────┬────────┐
▼ ▼ ▼ ▼ ▼
Linux 进程与 内存 文件 I/O
基础 线程 管理 系统 模型
│ │ │ │ │
├──用户态 ├──进程 ├──分页 ├──inode ├──BIO
│ /内核态 │ /线程 │ /分段 ├──软硬链接 ├──NIO
├──文件系统├──调度 ├──虚拟内存├──权限模型 ├──多路复用
└──Shell ├──IPC └──碎片 └──ext4 │ (select/
└──死锁 /分配 │ poll/
└ epoll)
建议学习顺序:先掌握 Linux 基础(用户态/内核态是核心概念),再学习进程与线程,然后是内存管理,接着是文件系统,最后是 I/O 模型。这个顺序确保每个知识点建立在前置知识之上。