阻塞 (Blocking I/O) 是最基础的 I/O 模型。用户进程在发起调用后会被挂起,直到数据完全准备好并拷贝到用户空间。
核心逻辑
在 Linux 中,默认创建的 Socket 都是阻塞的。其核心特征是“死等”:
- 进程挂起:调用
read/recv后,线程进入不可运行状态。 - 两阶段阻塞:
- 阶段一:等待数据到达内核缓冲区(等待硬件)。
- 阶段二:数据从内核缓冲区拷贝到用户缓冲区(CPU 拷贝)。
- 同步返回:只有两个阶段都完成,系统调用才返回。
同步 != 阻塞:为什么我觉得同步和阻塞是一回事情?不就是因为同步才阻塞的吗
sequenceDiagram participant U as 用户进程 participant K as 内核 (Kernel) U->>K: recvfrom (系统调用) Note over K: 阶段 1: 等待数据到达 K-->>K: 数据就绪 Note over K: 阶段 2: 拷贝数据到用户空间 K->>U: 返回成功/数据 Note over U: 进程恢复执行
优劣对比
- 优点:逻辑直观,符合线性思维,编程最简单。
- 缺点:并发能力极差。一个线程只能处理一个连接,高并发下会导致线程数爆炸,引发频繁的上下文切换和内存枯竭。
类比:去餐厅点餐,点完后死守在柜台前,不拿到菜绝不离开,期间什么也干不了。这就是“阻塞”。