与epoll媲美的io_uring

一 .io_uring简介

io_uring 是 Linux 内核提供的一种高性能的异步 I/O 框架。它旨在提供一种效率更高、更灵活的 I/O 模型,以满足现代应用程序对高吞吐量和低延迟 I/O 操作的需求。

传统的 I/O 模型(如阻塞 I/O 和非阻塞 I/O)在处理大量并发 I/O 操作时可能存在性能瓶颈。io_uring 通过提供一个高效的 I/O 操作队列和事件通知机制,允许应用程序以异步的方式提交 I/O 操作,同时避免了传统 I/O 模型中的一些开销,如系统调用的切换和数据拷贝。

二. io_uring 的主要特点

1. 异步操作

应用程序可以将 I/O 操作提交到 io_uring 队列中,并继续执行其他任务,而无需等待 I/O 操作完成。这样可以充分利用系统资源,并提高应用程序的并发性能。

2. 事件通知

io_uring 使用事件通知机制,例如使用 ring buffer 和 Completion Event Polling(完成事件轮询),以及 Linux 的 epoll 系统调用,来通知应用程序 I/O 操作的完成。

3. 零拷贝传输

io_uring 支持直接内存访问(Direct Memory Access,DMA)机制,可以在用户空间和内核空间之间进行零拷贝传输,减少了数据拷贝的开销。

4. 多功能性

io_uring 不仅支持常见的文件 I/O 操作,还可以处理网络套接字(sockets)的 I/O 操作,包括 TCP 和 UDP 的读写操作。

三 .io_uring 的系统调用函数

io_uring_setup()

用于初始化 io_uring 环。它创建了一个 io_uring 实例,并返回一个文件描述符,用于后续的 io_uring 操作。其原型为:

int io_uring_setup(unsigned entries, struct io_uring_params *p);
//参数 entries 指定了 io_uring 环的大小,而 io_uring_params 结构体包含了其他的一些初始化参数,如 io_uring 的特性和行为等。

io_uring_enter()

用于提交 I/O 操作到 io_uring 环。一旦 I/O 操作被提交,它会被内核异步处理。其原型为:

int io_uring_enter(int fd, unsigned to_submit, unsigned min_complete, unsigned flags, sigset_t *sig);
//参数 fd 是之前通过 io_uring_setup() 返回的文件描述符
to_submit 指定要提交的 I/O 操作数量
min_complete 指定最小要完成的 I/O 操作数量,flags 是控制 I/O 操作行为的一些标志
sig 是一个可选的信号集合,在完成 I/O 操作时通知应用程序

io_uring_register()

用于注册文件描述符到 io_uring 环中,以便进行 I/O 操作。其原型为:

int io_uring_register(int fd, unsigned opcode, const void *arg, unsigned nr_args);
//参数 fd 是文件描述符,opcode 是操作码,指定了要执行的操作类型,arg 是指向操作参数的指针,nr_args 是参数的数量。

四 .io_uring 常用编程函数

1. io_uring_queue_init();

用于初始化 io_uring 队列。它会分配并初始化一个 io_uring 对象,并返回一个指向该对象的指针。其原型为:

struct io_uring *io_uring_queue_init(unsigned entries, struct io_uring_params *p);

2. io_uring_prep_read(); / io_uring_prep_write();

用于准备读取和写入操作的函数。这些函数将指定的文件描述符和缓冲区等参数填充到 io_uring 操作数据结构中。其原型为:

void io_uring_prep_read(struct io_uring_sqe *sqe, int fd, void *buf, unsigned nbytes, off_t offset);
void io_uring_prep_write(struct io_uring_sqe *sqe, int fd, const void *buf, unsigned nbytes, off_t offset);

3. io_uring_submit();

用于将提交的 I/O 操作发送到 io_uring 环。其原型为:

int io_uring_submit(struct io_uring *ring);

4. io_uring_wait_cqe();

用于等待完成的 I/O 操作。当完成的操作可用时,它会返回一个指向完成的操作的指针。其原型为:

int io_uring_wait_cqe(struct io_uring *ring, struct io_uring_cqe **cqe_ptr);

5. io_uring_cqe_seen();

用于告知内核该完成的操作已经被处理,以便内核可以继续使用该完成队列项。其原型为:

void io_uring_cqe_seen(struct io_uring *ring, struct io_uring_cqe *cqe);

6. io_uring_peek_batch_cqe()与io_uring_wait_cqe()的区别

1.阻塞 vs 非阻塞

io_uring_wait_cqe() 是一个阻塞式函数。当你调用它时,如果没有完成的 I/O 操作,它会一直等待,直到有操作完成并且可用。
io_uring_peek_batch_cqe() 是一个非阻塞式函数。无论是否有完成的 I/O 操作,它都会立即返回。如果没有完成的操作,它返回 0。

2.处理方式

使用 io_uring_wait_cqe() 时,你等待操作完成,然后手动调用 io_uring_cqe_seen() 来告知内核这个完成队列项已经被处理过了。
使用 io_uring_peek_batch_cqe() 时,你可以立即得到完成的操作指针数组,你可以处理这些操作而不需要手动通知内核。

3.适用场景

io_uring_wait_cqe() 适用于需要等待操作完成后再继续执行的情况,比如在单线程中进行 I/O 操作的情况。
io_uring_peek_batch_cqe() 适用于不需要等待操作完成就可以继续执行的情况,比如在多线程环境中,可以同时处理多个完成的操作。

五 .io_uring 在 Linux 内核中的要求

  1. Linux 内核版本:io_uring 首次引入于 Linux 内核版本 5.1,因此要使用 io_uring,需要运行至少 Linux 内核 5.1 或更高版本( [uname -r] 查看linux系统内核版本)。

  2. 内核配置选项:为了启用 io_uring,您需要确保您的 Linux 内核配置中启用了以下选项:

    • CONFIG_IO_URING:这是 io_uring 模块的主要选项,用于启用和支持 io_uring 功能。
    • CONFIG_HAVE_IO_URING:这是一个辅助选项,用于检查系统是否支持 io_uring。

请注意,内核配置选项的名称可能会因不同的 Linux 发行版和内核版本而有所不同。可以查看您正在使用的 Linux 发行版的内核配置文档,以了解如何启用 io_uring。

  1. 用户空间库:为了在应用程序中使用 io_uring,需要链接并使用适当的用户空间库。目前,主要的 io_uring 用户空间库是 liburing。您需要安装 liburing 库,并在编译(-luring)和链接应用程序时引用它。

相关推荐

  1. epoll媲美io_uring

    2024-03-24 09:20:03       16 阅读
  2. windows版本epoll

    2024-03-24 09:20:03       13 阅读
  3. epoll使用示例及其解释

    2024-03-24 09:20:03       12 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-03-24 09:20:03       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-03-24 09:20:03       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-03-24 09:20:03       19 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-03-24 09:20:03       20 阅读

热门阅读

  1. [ABC298D] Writing a Numeral

    2024-03-24 09:20:03       17 阅读
  2. 备战蓝桥杯(前缀和、差分篇)

    2024-03-24 09:20:03       17 阅读
  3. 量化交易入门(十四)Python开发-matplotlib

    2024-03-24 09:20:03       16 阅读
  4. golang 使用AES加密

    2024-03-24 09:20:03       15 阅读
  5. opencv(4)

    2024-03-24 09:20:03       14 阅读
  6. C#获取HTML源码

    2024-03-24 09:20:03       17 阅读
  7. 在hf-mirror下载数据集的方式

    2024-03-24 09:20:03       13 阅读
  8. 【RPC研究】socket & 函数调用

    2024-03-24 09:20:03       17 阅读
  9. 518. 零钱兑换 II

    2024-03-24 09:20:03       18 阅读
  10. 对适配器模式的理解

    2024-03-24 09:20:03       18 阅读
  11. 编译cre2的一些问题

    2024-03-24 09:20:03       18 阅读
  12. HTML发展史

    2024-03-24 09:20:03       15 阅读
  13. AI大模型学习:深化技术与业务的融合创新

    2024-03-24 09:20:03       17 阅读