阻塞 (Blocking I/O) 是最基础的 I/O 模型。用户进程在发起调用后会被挂起,直到数据完全准备好并拷贝到用户空间。

核心逻辑

在 Linux 中,默认创建的 Socket 都是阻塞的。其核心特征是“死等”:

  1. 进程挂起:调用 read/recv 后,线程进入不可运行状态。
  2. 两阶段阻塞
    • 阶段一:等待数据到达内核缓冲区(等待硬件)。
    • 阶段二:数据从内核缓冲区拷贝到用户缓冲区(CPU 拷贝)。
  3. 同步返回:只有两个阶段都完成,系统调用才返回。

同步 != 阻塞:为什么我觉得同步和阻塞是一回事情?不就是因为同步才阻塞的吗

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: 进程恢复执行

优劣对比

  • 优点:逻辑直观,符合线性思维,编程最简单。
  • 缺点并发能力极差。一个线程只能处理一个连接,高并发下会导致线程数爆炸,引发频繁的上下文切换和内存枯竭。

类比:去餐厅点餐,点完后死守在柜台前,不拿到菜绝不离开,期间什么也干不了。这就是“阻塞”。