跳到主要内容
约 2 分钟1 张卡

I/O 模型

I/O 模型描述调用者如何等待数据与接收完成结果。本文以 Linux socket 读取为主,区分阻塞、非阻塞、就绪通知和异步完成;不同库使用的“异步”一词可能处于不同层次。

1. 面试核心​

先记住这几条,再读正文
  • 阻塞读取可让当前线程等待数据,非阻塞读取在暂不可用时返回 EAGAIN 等状态。
  • 就绪通知表示现在可以尝试 I/O,不表示应用数据已经处理完毕。
  • 异步完成通知对应已提交操作的结果,仍需处理缓冲区生命周期与错误。

2. 等待数据与执行读取​

网络数据先经过协议栈进入内核缓冲区,应用再通过 read/recv 等操作取得字节。阻塞 socket 在没有可读数据时可以使线程休眠;非阻塞 socket 则立即报告“现在无法完成”,让调用者继续处理其他工作。

这不是“所有调用都立刻完整成功”:读取可能只返回部分数据;写入也可能只接受部分字节。TCP 没有应用消息边界,解析完整消息需要自己积累字节并按协议分帧。

3. 就绪与完成​

就绪模型:等待可读事件 → 调用 read → 解析返回的字节
完成模型:提交读取操作 → 等待完成结果 → 使用返回的数据

I/O 多路复用帮助一个线程等待多个描述符的就绪状态。收到事件后仍要执行读取,并处理其他线程竞争、EOF 和错误。异步 API 也可能由库在线程池中包装阻塞调用,不能只看方法名就判断内核模型。

4. 使用边界​

非阻塞循环如果不断重试而不等待事件,会忙轮询并占用 CPU。事件循环中执行慢 SQL、文件操作或长计算,也会拖住其他连接。

普通磁盘文件上的 O_NONBLOCK 并不具有与 socket 相同的“绝不等待磁盘”保证。讨论非阻塞时必须明确对象、系统调用和运行时。Linux 网络服务器的常用组合见I/O 多路复用。

5 · 面试题卡片​

先想答案,再翻面题目来自公开面经。点任意一张进入翻卡,可左右切换,看完回到这里。
逐张翻看 1 张 →

5.1 阻塞和非阻塞 I/O 有什么区别,非阻塞是否就等于异步?​

出现公司:字节跳动

考察重点:暂不可用时的返回行为、就绪通知与异步完成的区别。

相关内容:面试核心、等待数据与执行读取、使用边界。

参考回答

区别在当前操作无法立即完成时调用者是否等待。非阻塞读取返回暂不可用后,通常仍由应用再次发起读取;它不自动形成异步完成机制。异步接口提交操作后以完成结果通知调用者,但实现可能来自内核,也可能是库线程池,因此需要限定讨论层次。

6. 参考资料​