当前位置: 首页 > news >正文

异步I/O和同步I/O

点外卖” 和 “自己做饭” 的生活场景来类比 Linux 中的 异步 I/O(AIO) 和 同步 I/O(Synchronous I/O)

1. 同步 I/O(Synchronous I/O)—— 自己做饭

场景

假设你饿了,决定 自己做饭

  1. 第一步:去菜市场买菜(相当于 read() 从磁盘读取数据)
    • 你必须亲自去菜市场,站在摊位前等老板把菜给你(阻塞)。
    • 如果菜市场没菜了,你得一直等(数据未就绪时阻塞)。
  2. 第二步:回家做饭(相当于 CPU 处理数据)
    • 买菜回来后,你才能开始洗菜、切菜、炒菜(顺序执行)。
  3. 第三步:吃饭(相当于程序继续执行后续逻辑)
    • 饭做好后,你才能吃(必须等前一步完成)。

同步 I/O 的特点

  • 阻塞:你必须亲自完成每一步,不能同时做其他事(比如不能一边买菜一边炒菜)。
  • 顺序执行:必须按 买菜 → 做饭 → 吃饭 的顺序来,不能跳过或并行。
  • 简单但低效:如果买菜或做饭很慢,你只能干等着,浪费时间。

Linux 中的同步 I/O 例子

  • read() / write():直接读写文件,如果数据没准备好,程序会卡住(阻塞)。
  • epoll() + 非阻塞 I/O:虽然可以同时监控多个文件描述符,但每次读写仍然需要手动检查数据是否就绪(类似“频繁去菜市场看菜到了没”)。

2. 异步 I/O(Asynchronous I/O, AIO)—— 点外卖

场景

假设你饿了,决定 点外卖

  1. 第一步:在手机上下单(相当于提交异步 I/O 请求)
    • 你只需要在美团/饿了么上点“提交订单”(非阻塞),然后可以继续刷抖音、打游戏(程序继续执行其他任务)。
  2. 第二步:外卖小哥送餐(相当于内核在后台处理 I/O)
    • 商家接单、做饭、打包、骑手取餐、送货,这些过程你完全不用管(内核在后台完成 I/O 操作)。
  3. 第三步:收到外卖通知(相当于回调函数或信号通知)
    • 手机“叮”一声,提示“外卖已送达”(通过回调或信号通知程序 I/O 完成)。
    • 你下楼取餐,然后吃饭(程序处理完成后的逻辑)。

异步 I/O 的特点

  • 非阻塞:下单后你可以继续干其他事,不用站在厨房等饭做好。
  • 并行处理:外卖小哥、商家、骑手可以同时工作(内核在后台高效处理 I/O)。
  • 高效但复杂:你需要留手机号(回调函数)或设置提醒(信号),否则可能错过外卖。

Linux 中的异步 I/O 例子

  • io_uring(Linux 5.1+ 推荐)
    • 像“美团外卖”一样高效,支持文件、网络等异步 I/O。
    • 程序提交订单(io_uring_prep_read),然后继续执行其他任务,内核完成后通知(io_uring_wait_cqe)。
  • libaio(较旧)
    • 类似“老式外卖平台”,功能有限,但也能实现异步文件 I/O。

3. 同步 vs 异步:外卖 vs 做饭

对比项同步 I/O(自己做饭)异步 I/O(点外卖)
是否阻塞阻塞(必须亲自等)非阻塞(下单后可以继续玩)
能否并行不能(一步接一步)能(商家、骑手、你同时干活)
效率低(浪费时间等)高(充分利用时间)
复杂度简单(按步骤来)复杂(需要处理通知)
适用场景低并发、简单任务(如单线程脚本)高并发、高性能需求(如 Web 服务器)

4. 实际代码类比

(1) 同步 I/O(自己做饭)

#include <unistd.h>
#include <stdio.h>int main() {char buf[1024];// 阻塞式读取文件(相当于站在菜市场等菜)ssize_t n = read(STDIN_FILENO, buf, sizeof(buf)); if (n > 0) {// 读取完成后才能继续处理(相当于做饭)write(STDOUT_FILENO, buf, n); }return 0;
}
  • 问题:如果 read() 很慢(比如从硬盘读取大文件),程序会卡住,无法做其他事。

(2) 异步 I/O(点外卖)

#include <liburing.h>
#include <fcntl.h>
#include <stdio.h>void callback(struct io_uring_cqe *cqe) {printf("外卖已送达!读取了 %d 字节\n", cqe->res);
}int main() {struct io_uring ring;io_uring_queue_init(32, &ring, 0); // 初始化“外卖平台”int fd = open("test.txt", O_RDONLY);char buf[1024];// 提交异步读请求(相当于下单)struct io_uring_sqe *sqe = io_uring_get_sqe(&ring);io_uring_prep_read(sqe, fd, buf, sizeof(buf), 0);io_uring_submit(&ring); // 告诉内核:“我点单了,你去做吧!”printf("下单成功!继续刷抖音...\n"); // 程序继续执行其他任务// 稍后检查外卖状态(相当于等手机通知)struct io_uring_cqe *cqe;io_uring_wait_cqe(&ring, &cqe);callback(cqe); // 处理完成事件(取外卖)io_uring_cqe_seen(&ring, cqe); // 标记“已取餐”io_uring_queue_exit(&ring);close(fd);return 0;
}
  • 优势:提交请求后,程序可以继续做其他事,内核在后台高效处理 I/O。

5. 总结

  • 同步 I/O(自己做饭):简单但低效,适合简单任务。
  • 异步 I/O(点外卖):高效但复杂,适合高并发场景(如 Nginx、Redis、数据库)。
  • Linux 推荐
    • 高性能文件 I/O:io_uring(现代外卖平台)
    • 网络 I/O:epoll() + 非阻塞 I/O(类似“多线程做饭”)
http://www.lryc.cn/news/605635.html

相关文章:

  • Day15--二叉树--222. 完全二叉树的节点个数,110. 平衡二叉树,257. 二叉树的所有路径,404. 左叶子之和
  • 在Linux中创建LVGL应用
  • Kotlin -> 普通Lambda vs 挂起Lambda
  • 【Django】-1- 开发项目搭建
  • Django模型迁移指南:从命令用法到最佳实践
  • HttpServletRequest详细解释
  • 如何在NPM上发布自己的React组件(包)
  • 人工智能概念之十一:常见的激活函数与参数初始化
  • Cesium 快速入门(四)相机控制完全指南
  • langchain--1--prompt、output格式、LCEL示例
  • 【烧脑算法】Dijkstra 算法:解决最短路问题
  • 会议室预定系统核心技术:如何用一行SQL解决时间冲突检测难题
  • LLC电源原边MOS管DS增加RC吸收对ZVS的影响分析
  • ode with me是idea中用来干嘛的插件
  • 山东移动云主机:技术架构与特性解析
  • AI 安监系统:为工业园安全保驾护航
  • 1 机器学习概述 (第一天2025.7.31)
  • RabbitMQ 队列配置设置 RabbitMQ 消息监听器的并发消费者数量java
  • Java 大视界 -- Java 大数据在智能医疗远程健康监测与疾病预防预警中的应用(374)
  • Linux 进程管理与计划任务
  • linux git ssh配置过程
  • React中的this绑定
  • SpringMVC的核心架构与请求处理流程
  • PostgreSQL dblink 与 Spring Boot @Transactional 的事务整合
  • 网络层概述
  • AngularJS 事件
  • Web 开发 08
  • 智慧社区项目开发(四)——前后端登录认证相关功能实现解析
  • 网关 + MDC 过滤器方案,5分钟集成 日志 traceid
  • Gemini Fullstack LangGraph Quickstart(DeepSeek+Tavily版本)