磁盘与 IO
→ 返回计算机基础
磁盘是计算机的持久化存储介质,IO(Input/Output)是 CPU 与外部设备交换数据的过程。两者的性能特征直接影响系统整体吞吐量。
磁盘结构
HDD(机械硬盘)
盘片(Platter)— 多个叠放,双面存储
磁道(Track) — 盘面上的同心圆
扇区(Sector) — 磁道的最小存储单元(通常 512 B 或 4 KB)
柱面(Cylinder)— 所有盘面相同磁道的集合
磁头(Head) — 每个盘面一个,负责读写
访问时间 = 寻道时间(5–15 ms)+ 旋转延迟(3–6 ms)+ 数据传输时间
SSD(固态硬盘)
基于 NAND Flash,无机械运动:
| 特性 | HDD | SSD |
|---|---|---|
| 随机读写延迟 | ~10 ms | ~0.1 ms |
| 顺序读速度 | ~200 MB/s | 500 MB/s–7 GB/s |
| 抗震 | 差 | 好 |
| 写寿命 | 无限制 | 有限(P/E 次数) |
SSD 写入需先擦除(块粒度),FTL(Flash Translation Layer)负责地址映射与磨损均衡。
磁盘调度算法(HDD)
| 算法 | 说明 | 特点 |
|---|---|---|
| FCFS | 按请求顺序服务 | 公平,磁头移动距离大 |
| SSTF | 每次服务最近磁道 | 平均寻道短,可能饥饿 |
| SCAN(电梯) | 磁头单向扫描到端再折返 | 均匀,无饥饿 |
| C-SCAN | 单方向扫描,折返直接跳回起点 | 更均匀的等待时间 |
| LOOK/C-LOOK | 到最后一个请求即折返 | 减少不必要移动 |
IO 控制方式
| 方式 | 说明 | 适用 |
|---|---|---|
| 程序轮询(Polling) | CPU 不断查询设备状态 | 简单低速设备 |
| 中断驱动 | 设备完成后发中断通知 CPU | 通用设备 |
| DMA(直接内存访问) | DMA 控制器独立传输,完成后中断 CPU | 高速大批量传输 |
IO 模型
阻塞 IO
应用调用 read() → 内核等待数据就绪 → 拷贝到用户空间 → 返回
(全程阻塞线程)
非阻塞 IO
应用调用 read() → 无数据立即返回 EAGAIN → 应用轮询重试
(CPU 空转,浪费资源)
IO 多路复用
用 select/poll/epoll 同时监听多个 fd,任意就绪即通知:
| select | poll | epoll | |
|---|---|---|---|
| fd 上限 | 1024 | 无限制 | 无限制 |
| 扫描复杂度 | O(n) | O(n) | O(1)(事件回调) |
epoll 是 Linux 高性能服务器(Nginx、Redis)的核心机制。
异步 IO(AIO)
应用发起 aio_read() → 立即返回,继续执行其他逻辑
内核完成数据拷贝后 → 通知应用
Linux io_uring(内核 5.1+)是当前性能最优的异步 IO 实现。
零拷贝(Zero-Copy)
传统文件发送路径(4 次数据拷贝,2 次系统调用):
磁盘 --DMA-→ 内核缓冲区 --CPU-→ 用户空间 --CPU-→ Socket 缓冲区 --DMA-→ 网卡
零拷贝优化:
| 方式 | 原理 | 拷贝次数 |
|---|---|---|
sendfile() | 数据在内核态直接从文件 fd 传到 Socket | 2(均为 DMA) |
mmap + write | 文件映射到用户空间,减少一次内核→用户拷贝 | 3 |
splice() | 利用内核管道在 fd 间移动数据 | 2 |
RAID
| 级别 | 说明 | 最多容忍故障盘 | 容量利用率 |
|---|---|---|---|
| RAID 0 | 条带化,无冗余 | 0 | 100% |
| RAID 1 | 镜像 | 1 | 50% |
| RAID 5 | 条带 + 分布式奇偶校验 | 1 | (n-1)/n |
| RAID 6 | 双奇偶校验 | 2 | (n-2)/n |
| RAID 10 | RAID 1 + RAID 0 | 每镜像组 1 | 50% |