io_uring如何实现异步读取?

问题描述 投票:0回答:1

最近,我一直在尝试将异步读取合并到现有功能中,并想到了 io_uring。我阅读了互联网上的文档,感觉 io_uring 生成了一个新线程 io-wrk 来执行操作。但我无法看到该线程的产生。我正在使用以下标志打开文件:

fd = open("file1.txt", O_DIRECT | O_RDONLY)

我正在尝试查看以下线程

top -H -p <pid_of_process>

编辑-

liburing 片段用于生成 io_uring 并提交读取请求

struct io_uring params;
memset(&params, 0 , sizeof(params));
io_uring_queue_init_params(128, &ring, &params);

char* ptr = (char*)aligned_alloc(512, 4096);
auto sqe = io_uring_get_sqe(&ring)
io_uring_prep_read(sqe, fd, ptr, 4096, -1);

非常感谢任何有关正在发生的事情的帮助。

c++ linux multithreading asynchronous io-uring
1个回答
0
投票

据我所知,io_uring 不会产生任何用户线程。话虽这么说,可以根据 io_uring 的设置方式生成内核线程。

设置功能是

io_uring_setup
并且可以进行多种配置。其中一些不应该创建内核线程,而另一些则应该。例如,通过中断驱动的配置,内核可以避免创建后台内核线程,因为可以在调用
io_uring_enter
期间完成进程。或者,使用内核轮询策略,唯一可能的实现是创建一个内核线程,因为只要池内核线程没有休眠(但可以由应用程序使用特殊的方法唤醒它),无需执行任何系统调用即可保证进程。
io_uring_enter
按照上述手动链接中的说明进行调用)。有关可能的高级模式的更多信息,请参阅这篇文章)。

使用 liburing,基于

io_uring_queue_init
的函数根据提供的参数结构或标志调用
io_uring_setup
。由于您的标志在调用
io_uring_queue_init_params
之前被手动初始化为零,并且 liburing 直接通过
io_uring_setup
传递 params 指示的参数,因此我希望所有标志都被禁用。 (长)手册具体说明了在这种情况下会发生什么(尽管在中间):

如果未指定标志,则为 中断驱动的 I/O 设置 io_uring 实例。 I/O 可以使用 io_uring_enter(2) 提交,并可以通过轮询完成队列来获取。

除了以下适用的默认行为之外:

io_uring 将在任何系统调用或线程中断结束时处理所有未完成的工作

当完成事件到来时,

io_uring 将中断在用户空间中运行的任务。这是为了确保及时完成。 [...]。大多数应用程序不需要强制中断,因为事件是在任何内核/用户转换时处理的。 [...]

这并没有指定实现是否在中断驱动模式下创建内核线程(这是您案例中使用的模式)。我认为这取决于实施情况并且可能会改变。默认情况下,如果它不创建一个,那么在任何系统调用结束时都会确保进程,如果创建了,那么内核线程将导致用户进程被中断。

如果你想要一个内核线程来确保异步IO操作的进展,那么我认为你应该使用另一种模式来强制执行,比如

IORING_SETUP_SQPOLL
:

指定此标志时,将创建一个内核线程来执行提交队列轮询。以这种方式配置的 io_uring 实例使应用程序能够发出 I/O,而无需上下文切换到内核。通过使用提交队列填充新的提交队列条目并监视完成队列上的完成情况,应用程序无需执行单个系统调用即可提交和获取 I/O。

我建议您仔细阅读此模式的详细信息,因为它的影响不可忽视(例如,在

io_uring_enter
系统调用和 liburing
io_uring_submit
)。

© www.soinside.com 2019 - 2024. All rights reserved.