基于异步IO的io_uring

news/2025/1/14 6:42:07/

基于异步IO的io_uring

1. io_uring的实现原理

io_uring使用了一种异步IO机制,它通过一对环形缓冲区(ring buffer)实现用户态于内核态之间的高效通信,用户只需将IO请求放入提交队列,当内核完成IO请求时,会将结果放入完成队列,然后用户从完成队列中提取结果并进行后序处理。

io_uring中的两个队列是映射到用户态的共享内存区域,用户态和内核态可以直接通过这个区域交换数据,减少了系统调用上下文切换。用户也可以一次性提交多个IO请求,减少了系统调用次数。

io_uring在内核中有专门的work线程来处理用户请求,完成IO操作,并且worker线程数量也是内核根据cpu核心数和负载情况自己调节的。

io_uring的优点:

  1. 高并发,通过异步IO机制,一个线程能够同时进行大量的IO处理,不会产生阻塞。
  2. 高性能低延迟,读写操作在内核态完成,并且IO请求和IO结果都是通过共享内存来传递的,减少了系统调用和上下文切换次数。

2. liburing的使用流程

2.1 多线程设计

  1. 每个线程一个io_uring–> 不用考虑同步,但是浪费资源
  2. 一个io_uring线程加一个线程池处理任务 --> 需要考虑同步问题
  3. 多个线程使用一个io_uring,同样需要考虑同步问题

2.2 流程

  1. 创建 io_uring 实例

    int ret = io_uring_queue_init(32, &ring, 0);  // 初始化 io_uring 实例,队列深度为 32
    
  2. 填充IO请求

    sqe = io_uring_get_sqe(&ring);  // 获取一个提交队列入口io_uring_prep_write(sqe, fd, buf, strlen(buf), 0);  // 写入文件
    io_uring_prep_read(sqe, fd, buf, sizeof(buf), 0);  // 异步读取文件
    
  3. 提交IO请求

    int submitted = io_uring_submit(&ring);  // 提交请求到内核
    
  4. 等待IO请求完成

    int ret = io_uring_wait_cqe(&ring, &cqe);  // 等待完成队列中的一个请求完成
    io_uring_cqe_seen(&ring, cqe);  // 告诉 io_uring 已经处理完该完成队列入口
    
  5. 清理资源

    io_uring_cqe_seen(&ring, cqe);  // 告诉 io_uring 已经处理完该完成队列入口
    

3. proactor网络模型

proactor网络模型是一种异步IO事件驱动的模型,它向内核提交IO请求,然后等待内核完成IO操作后,再提取结果。它与reactor一样都是高性能、高并发的网络模型,与reactor的区别在于,IO事件的处理是在内核态完成的,用户直接获取IO操作的结果。

Proactor 模式的关键思想是将 I/O 操作的处理责任交给操作系统,应用程序只负责发起请求和处理回调。

proactor的优点

  1. 高性能的异步IO,IO操作在内核态完成,内核完成后将结果通知用户,因此能够减少系统调用和上下文切换,提高性能。
  2. 高并发,和reactor一样,都能够用一个线程同时处理大量连接的IO请求,只不过reactor依靠的是IO多路复用机制,而proactor依赖的异步IO。
  3. 线程复用性,和reactor一样,proactor也可以减少线程的切换、创建、销毁的开销,节约线程资源,程序的局部性更好,对缓存更友好。

4. proactor模式的使用场景

  • 高性能、高并发、内核5.1以上

4.1 reactor对比proactor

  1. IO事件处理上reactor在用户态处理IO操作,用户需要注册事件、等待事件发生,然后在用户态调用IO操作;而proactor模式在内核处理IO操作,用户只需提交异步IO请求,然后等待和获取IO操作的结果,内核态的worker线程会进行实际的IO操作。
  2. 性能上:由于proactor模式由内核来负责处理IO操作,减少了系统调用和上下文切换次数,性能较强。经过实测,在echo回声应用上测试16、64、512、1024长度消息,proactor的性能平均要比epoll高10%左右。

http://www.ppmy.cn/news/1562974.html

相关文章

MySQL主从:如何处理“Got Fatal Error 1236”或 MY-013114 错误(percona译文)

错误的 GTID 如今,典型的复制设置使用 GTID 模式,完整的错误消息可能如下所示: mysql > show replica status\G *************************** 1. row ***************************Replica_IO_Running: NoReplica_SQL_Running: YesLast_I…

CKA | Docker容器技术概述

往期文章推荐 【新版】容器&Kubernetes认证管理员(CKA)课程介绍 k8s-CKS认证课程介绍 【K8s】Kubernetes 词汇表 什么是Docker容器? 3个管理多k8s集群实用工具 K8S-CKA课程试听:Container 概述 CKA课程 | Docker容器技术概述 今日分…

Java Spring的@Async的使用及注意事项

1、概念和用途 Async是 Spring 框架提供的一个注解,用于标记一个方法,在一个单独的线程中异步执行。 这在处理一些耗时的操作(比如发送邮件、调用外部 API 等)时非常有用。 通过使用Async,可以让这些操作在后台执行…

Excel 技巧07 - 如何计算到两个日期之间的工作日数?(★)如何排除节假日计算两个日期之间的工作日数?

本文讲了如何在Excel中计算两个日期之间的工作日数,以及如何排除节假日计算两个日期之间的工作日数。 1,如何计算到两个日期之间的工作日数? 其实就是利用 NETWORKDAYS.INTL 函数 - weekend: 1 - 星期六,星期日 2,如…

基于Auto-Editor一键预处理音视频无声片段

在视频制作与后期处理中,长时间的无声片段往往会增加视频观看的乏味感,尤其在讲解类口播视频中,这种片段频繁出现。因此,自动识别并删除这些无声片段的需求逐渐增多。Auto-Editor是一款开源的自动化视频编辑工具,它通过自动检测音频信号,可以一键删除无声片段,大大提高视…

pytorch小记(四):pytorch中的重排操作:x.permute()

pytorch小记(四):pytorch中的重排操作:x.permute() 1. 初始张量 x2. 调用 permute 的原理案例分析2.1 z x.permute(0, 2, 1)2.2 z x.permute(1, 0, 2)2.3 z x.permute(1, 2, 0)2.4 z x.permute(2, 0, 1…

【JVM-1】深入解析JVM:Java虚拟机的核心原理与工作机制

Java虚拟机(JVM,Java Virtual Machine)是Java技术的核心,它使得Java程序能够“一次编写,到处运行”。无论是Java开发者还是对技术感兴趣的爱好者,理解JVM的工作原理都是非常重要的。本文将深入探讨JVM的核心…

CentOS 和 Ubantu你该用哪个

文章目录 **一、CentOS 和 Ubuntu 的详细介绍****1. CentOS****1.1 基本信息****1.2 特点****1.3 缺点** **2. Ubuntu****2.1 基本信息****2.2 特点****2.3 缺点** **二、CentOS 和 Ubuntu 的异同****1. 相同点****2. 不同点****3. 使用体验对比** **三、总结和选择建议** Cent…