本文介绍了io_uring的percpu sqthread使用方法及常见故障码的处理
背景介绍
io_uring
是Linux内核中的一种高性能异步I/O接口,通过一对共享内存缓冲区(ring buffer)实现应用程序和内核之间的高效通信,从而提高性能和效率。sqpoll
是io_uring的一个特性,会启用一个单独的内核线程来处理提交队列(SQ)中的任务,这个线程称为sqthread
。
如果在同一个进程内创建多个io_uring实例并开启了sqpoll
,可能会出现所有的sqthread都运行在同一个核上的情况——每个io_uring实例都会开启一个单独的sqthread线程,导致单一核上同时运行多个sqthread线程。这种情况下,sqthread上下文切换将带来较多不必要的开销。为了实现高效的sqpoll功能并降低使用难度,Alibaba Cloud Linux 3 提供了io_uring的percpu sqthread
特性,允许您在创建sqthread时指定其所在的核。此外,在同一个核上最多只存在一个sqthread,该sqthread会轮询处理绑定自己的所有io_uring实例的请求。
使用限制
操作系统:Alibaba Cloud Linux 3。
内核版本:5.10.112-11及更高版本。
使用percpu sqthread特性
启用 percpu sqthread
在初始化 io_uring时,需要设置 IORING_SETUP_SQPOLL
标志来启用sqpoll模式。此外,为了使能percpu sqthread特性,还需要配置 IORING_SETUP_SQPOLL_PERCPU
和 IORING_SETUP_SQ_AFF
。同时,需要通过 sq_thread_cpu
指定绑定到sqthread所在的CPU序号。具体示例如下所示:
struct io_uring ring;
struct io_uring_params params = {};
params.flags = IORING_SETUP_SQPOLL|IORING_SETUP_SQPOLL_PERCPU|IORING_SETUP_SQ_AFF;
params.sq_thread_cpu = 1;
ret = io_uring_queue_init_params(ENTRIES, &ring, ¶ms);
if (ret < 0) {
perror("io_uring_queue_init_params");
exit(EXIT_FAILURE);
}
提交和处理I/O请求
使用
io_uring_sqe
结构体准备 I/O 请求。struct io_uring_sqe *sqe = io_uring_get_sqe(&ring); if (!sqe) { fprintf(stderr, "get sqe failed\n"); return -1; } io_uring_prep_read(sqe, fd, buf, len, offset); sqe->user_data = (uint64_t)buf;
使用
io_uring_submit
函数将请求提交到 SQ。ret = io_uring_submit(&ring); if (ret < 0) { perror("io_uring_submit"); return -1; }
使用
io_uring_wait_cqe
或io_uring_peek_cqe
函数从CQ中获取完成的I/O请求。struct io_uring_cqe *cqe; ret = io_uring_wait_cqe(&ring, &cqe); if (ret < 0) { perror("io_uring_wait_cqe"); return -1; } if (cqe->res < 0) { fprintf(stderr, "read error: %s\n", strerror(-cqe->res)); } else { printf("read %d bytes\n", cqe->res); } io_uring_cqe_seen(&ring, cqe);
常见问题
- 本页导读 (1)
- 背景介绍
- 使用限制
- 使用percpu sqthread特性
- 启用 percpu sqthread
- 提交和处理I/O请求
- 常见问题
- Q1:创建io_uring时返回错误代码-1(Operation Not Permitted)
- Q2:创建io_uring时返回错误代码-22(Invalid Parameter)