当前位置:首页 > 科技  > 软件

图文详解io_uring高性能异步IO架构(原理篇)

来源: 责编: 时间:2024-01-02 09:32:02 330观看
导读说到高性能网络编程,我们第一时间想到的是epoll机制,epoll很长一段时间统治着整个网络编程江湖,然而io_uring的出现,似乎在撼动epoll的统治地位,今天我们来揭开io_uring的神秘面纱。1.io_uring简介io_uring是一个Linux内核

说到高性能网络编程,我们第一时间想到的是epoll机制,epoll很长一段时间统治着整个网络编程江湖,然而io_uring的出现,似乎在撼动epoll的统治地位,今天我们来揭开io_uring的神秘面纱。jCY28资讯网——每日最新资讯28at.com

1.io_uring简介

io_uring是一个Linux内核的异步I/O框架,它提供了高性能的异步I/O操作,io_uring的目标是通过减少系统调用和上下文切换的开销来提高I/O操作的性能。jCY28资讯网——每日最新资讯28at.com

io_uring通过使用环形缓冲区和事件驱动的方式来实现高效的异步I/O操作。jCY28资讯网——每日最新资讯28at.com

io_uring的设计使得应用程序可以同时处理大量的I/O操作,从而提高系统的吞吐量和响应速度。jCY28资讯网——每日最新资讯28at.com

2.io_uring实现原理

io_uring整体架构如下:jCY28资讯网——每日最新资讯28at.com

图片图片jCY28资讯网——每日最新资讯28at.com

2.1基础概念

  • SQE:提交队列项,表示IO请求。
  • CQE:完成队列项,表示IO请求结果。
  • SQ:Submission Queue,提交队列,用于存储SQE的数组。
  • CQ:Completion Queue,完成队列,用于存储CQE的数组。
  • SQ Ring:SQ环形缓冲区,包含SQ,头部索引(head),尾部索引(tail),队列大小等信息。
  • CQ Ring:CQ环形缓冲区,包含SQ,头部索引(head),尾部索引(tail),队列大小等信息。
  • SQ线程:内核辅助线程,用于从SQ队列获取SQE,并提交给内核处理,并将IO请求结果生成CQE存储在CQ队列。

2.2 io_uring系统调用

  • io_uring_setup():用于初始化io_uring环境,创建io_uring实例。
  • io_uring_enter():用于提交和等待io_uring操作的系统调用,可以指定提交的操作数量和等待的超时时间。
  • io_uring_register():用于注册文件描述符或事件文件描述符到io_uring实例中,以便进行I/O操作。

2.3 liburing库

liburing是一个用于Linux的用户空间库,用于利用io_uring接口进行高性能的异步I/O操作,它提供了一组函数和数据结构,使开发者能够更方便地使用io_uring接口。jCY28资讯网——每日最新资讯28at.com

  • io_uring_queue_init:初始化一个io_uring队列。
  • io_uring_register:将文件描述符注册到io_uring队列中。
  • io_uring_prep_read:准备一个读取操作。
  • io_uring_prep_write:准备一个写入操作。
  • io_uring_submit:提交一个或多个操作到io_uring队列中。
  • io_uring_wait_cqe:等待一个完成的操作。
  • io_uring_cqe_seen:标记一个完成的操作已经被处理。
  • io_uring_queue_exit:关闭并释放io_uring队列。

2.4 工作流程

  1. 创建io_uring对象:首先,需要创建一个io_uring对象,可以使用io_uring_setup()函数来完成。
  2. 准备I/O请求:在进行I/O操作之前,需要准备相关的I/O请求。可以使用io_uring_prep_XXX()系列函数来准备不同类型的I/O请求,例如io_uring_prep_read()用于读取数据,io_uring_prep_write()用于写入数据。
  3. 提交I/O请求:准备好I/O请求后,可以使用io_uring_submit()函数将请求提交给内核,内核会将这些请求放入一个队列中,等待执行。
  4. 等待IO请求完成:可以使用io_uring_wait_cqe()函数来等待I/O请求的完成,一旦请求完成,内核会将完成事件放入一个完成队列中。
  5. 获取IO请求结果:可以使用io_uring_peek_cqe()函数来获取完成队列中的完成事件。然后,可以通过事件的信息来处理完成的I/O请求,例如读取数据或者处理错误。
  6. 释放IO请求结果:获取完IO请求结果,使用io_uring_cqe_seen()函数来释放IO请求结果,以便内核可以继续使用。
  7. 重复执行:可以重复执行上述步骤,以处理更多的I/O请求。

3.内核实现

3.1 创建io_uring对象

图片图片jCY28资讯网——每日最新资讯28at.com

用户程序通过io_uring_setup系统调用创建和初始化io_uring对象,io_uring对象对应于struct io_ring_ctx结构体对象。jCY28资讯网——每日最新资讯28at.com

io_uring_setup主要工作:jCY28资讯网——每日最新资讯28at.com

  • 创建struct io_ring_ctx对象并初始化。
  • 创建struct io_urings对象并初始化,注意此时已完成CQ和所有CQE创建。
  • 创建SQ和所有SQE并初始化。
  • 如果struct io_ring_ctx对象flags参数设置IORING_SETUP_SQPOLL,则创建SQ线程。

3.2 fd绑定io_uring对象

图片图片jCY28资讯网——每日最新资讯28at.com

已创建的io_ring对象需要和fd进行绑定, 以便能够通过fd找到io_uring对象,创建一个新的file,file private_data成员指向io_ring对象,申请一个未使用的文件描述符fd,fd映射至file,并存储在进程已打开文件表中。jCY28资讯网——每日最新资讯28at.com

注意:mmap内存映射需要用到该fd。jCY28资讯网——每日最新资讯28at.com

3.3 io_uring对象内存映射

图片图片jCY28资讯网——每日最新资讯28at.com

通过io_uring_setup系统调用创建完io_uring对象后,用户程序还不能直接访问io_uring对象,此时用户程序需要通过mmap函数将io_uring对象SQ,CQ以及head和tail等相关内存空间映射出来。jCY28资讯网——每日最新资讯28at.com

完成mmap内存映射后,io_uring对象相关内存空间成为用户程序和内核共享内存空间,用户程序可以直接访问io_uring对象,不再需要通过执行系统调用访问,很大程度上提高了系统性能。jCY28资讯网——每日最新资讯28at.com

3.4 提交IO请求jCY28资讯网——每日最新资讯28at.com

图片图片jCY28资讯网——每日最新资讯28at.com

SQ Ring中有两个成员head(头部索引)和tail(尾部索引),头部索引指向SQ队列第一个已提交IO请求,尾部索引指向SQ下一个空闲SQE。jCY28资讯网——每日最新资讯28at.com

提交IO请求,只需要将tail指向的SQE填充IO请求信息,并让tail自增1,指向下一个空闲SQE。jCY28资讯网——每日最新资讯28at.com

注意:head和tail不是直接指向SQ数组,而是需要通过head&mask和tail &mask操作指向SQ数组,mask数组为数组长度减1,因为数组有固定大小,所以需要通过&mask方式防止越界访问数组,这种方式可以让数组形成一个环形缓冲区。jCY28资讯网——每日最新资讯28at.com

3.5 等待IO请求完成jCY28资讯网——每日最新资讯28at.com

图片图片jCY28资讯网——每日最新资讯28at.com

IO请求的处理有两种方式:jCY28资讯网——每日最新资讯28at.com

  • 方式1:SQ线程从SQ队列中获取SQE(已提交IO请求),并发送给内核处理。
  • 方式2:用户程序通过io_uring_enter系统调用从SQ队列中获取SQE(已提交IO请求),并发送给内核处理。

从SQ队列获取SQE只需要获取SQ Ring head指向的SQE,并让head自增指向下一个SQE即可。jCY28资讯网——每日最新资讯28at.com

图片图片jCY28资讯网——每日最新资讯28at.com

内核处理完IO请求后,SQ线程会申请CQ Ring tail指向的CQE存储IO请求结果,tail自增1指向下一个空闲CQE。jCY28资讯网——每日最新资讯28at.com

3.6 获取IO请求结果

图片图片jCY28资讯网——每日最新资讯28at.com

用户程序通过判断CQ Ring head和tail之间的差值,可以检测到是否有已完成IO请求,如果有已完成IO请求(CQE),获取CQ Ring head指向CQE,获取IO请求结果。jCY28资讯网——每日最新资讯28at.com

3.7 释放已完成IO请求

释放已完成IO请求只需要将CQ Ring head指针自增1指向下一个CQE即可,这样做的目的是防止重复获取IO请求结果。jCY28资讯网——每日最新资讯28at.com

io_uring为什么高效?jCY28资讯网——每日最新资讯28at.com

核心原因:io_uring通过mmap内存映射大大减少了系统调用,在高并发场景下,系统调用非常损耗系统性能。jCY28资讯网——每日最新资讯28at.com

其他原因:jCY28资讯网——每日最新资讯28at.com

  • 减少拷贝:io_uring通过共享内存减少用户程序和内核数据拷贝。
  • 批量操作:io_uring支持批量操作,一次性可以提交多个I/O请求,减少系统调用的次数,提高系统效率。
  • 无锁环形队列:io_uring采用无锁队列实现用户程序与内核对共享内存的高效访问。

本文链接:http://www.28at.com/showinfo-26-55362-0.html图文详解io_uring高性能异步IO架构(原理篇)

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: Redis中Leader-Follower架构如何确保数据一致性和可靠性?

下一篇: 图文详解io_uring高性能异步IO架构(原理篇)

标签:
  • 热门焦点
  • 直屏旗舰来了 iQOO 12和K70 Pro同台竞技

    旗舰机基本上使用的都是双曲面屏幕,这就让很多喜欢直屏的爱好者在苦等一款直屏旗舰,这次,你们等到了。据博主数码闲聊站带来的最新爆料称,Redmi下代旗舰K70 Pro和iQOO 12两款手
  • 小米降噪蓝牙耳机Necklace分享:听一首歌 读懂一个故事

    在今天下午的小米Civi 2新品发布会上,小米还带来了一款新的降噪蓝牙耳机Necklace,我们也在发布结束的第一时间给大家带来这款耳机的简单分享。现在大家能见到最多的蓝牙耳机
  • 7月安卓手机好评榜:三星S23Ultra好评率第一

    性能榜和性价比榜之后,我们来看最后的安卓手机好评榜,数据来源安兔兔评测,收集时间2023年7月1日至7月31日,仅限国内市场。第一名:三星Galaxy S23 Ultra好评率:95.71%在即将迎来新
  • 5月安卓手机好评榜:魅族20 Pro夺冠

    性能榜和性价比榜之后,我们来看最后的安卓手机好评榜,数据来源安兔兔评测,收集时间2023年5月1日至5月31日,仅限国内市场。第一名:魅族20 Pro好评率:97.50%不得不感慨魅族老品牌还
  • 0糖0卡0脂 旭日森林仙草乌龙茶优惠:15瓶到手29元

    旭日森林无糖仙草乌龙茶510ml*15瓶平时要卖为79.9元,今日下单领取50元优惠券,到手价为29.9元。产品规格:0糖0卡0脂,添加草本仙草汁,清凉爽口,富含茶多酚,保留
  • 一文搞定Java NIO,以及各种奇葩流

    大家好,我是哪吒。很多朋友问我,如何才能学好IO流,对各种流的概念,云里雾里的,不求甚解。用到的时候,现百度,功能虽然实现了,但是为什么用这个?不知道。更别说效率问题了~下次再遇到,
  • 拼多多APP上线本地生活入口,群雄逐鹿万亿市场

    Tech星球(微信ID:tech618)文 | 陈桥辉 Tech星球独家获悉,拼多多在其APP内上线了“本地生活”入口,位置较深,位于首页的“充值中心”内,目前主要售卖美食相关的
  • 小米公益基金会捐赠2500万元驰援北京、河北暴雨救灾

    8月2日消息,今日小米科技创始人雷军在其微博上发布消息称,小米公益基金会宣布捐赠2500万元驰援北京、河北暴雨救灾。携手抗灾,京冀安康!以下为公告原文
  • 8月见!小米MIX Fold 3获得3C认证:支持67W快充

    这段时间以来,包括三星、一加、荣耀等等有不少品牌旗下的最新折叠屏旗舰都得到了不少爆料,而小米新一代折叠屏旗舰——小米MIX Fold 3此前也屡屡被传
Top