io_uring的percpu sqthread特性使用说明

更新时间:2025-03-27 03:19:04

本文介绍了io_uringpercpu sqthread使用方法及常见故障码的处理

背景介绍

io_uringLinux内核中的一种高性能异步I/O接口,通过一对共享内存缓冲区(ring buffer)实现应用程序和内核之间的高效通信,从而提高性能和效率。sqpollio_uring的一个特性,会启用一个单独的内核线程来处理提交队列(SQ)中的任务,这个线程称为sqthread

如果在同一个进程内创建多个io_uring实例并开启了sqpoll,可能会出现所有的sqthread都运行在同一个核上的情况——每个io_uring实例都会开启一个单独的sqthread线程,导致单一核上同时运行多个sqthread线程。这种情况下,sqthread上下文切换将带来较多不必要的开销。为了实现高效的sqpoll功能并降低使用难度,Alibaba Cloud Linux 3 提供了io_uringpercpu 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, &params);
if (ret < 0) {
    perror("io_uring_queue_init_params");
    exit(EXIT_FAILURE);
}

提交和处理I/O请求

  1. 使用 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;
  2. 使用 io_uring_submit 函数将请求提交到 SQ。

    ret = io_uring_submit(&ring);
    if (ret < 0) {
        perror("io_uring_submit");
        return -1;
    }
  3. 使用 io_uring_wait_cqeio_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);

常见问题

Q1:创建io_uring时返回错误代码-1(Operation Not Permitted)

例如,在调用 __sys_io_uring_setup 函数创建io_uring时,返回值为-1(EPERM)。

原因及其解决方案

当前进程与最初在该CPU上创建的sqthread所属进程不同。percpu sqthread 特性仅支持进程内的sqthread共享,即如果A进程第一次在XCPU上创建了sqthread,只允许同一进程的不同线程共享该sqthread。此时如果B进程要应用该特性,请选择不同的CPU号绑定。

Q2:创建io_uring时返回错误代码-22(Invalid Parameter)

例如,在调用 __sys_io_uring_setup 函数创建io_uring时,返回值为-22(EINVAL)。

此时请检查 sq_thread_cpu 参数是否合规。 sq_thread_cpu 会指定 io_uring 实例所绑定的sqthread所在的CPU号,该CPU需要是一个有效值(小于等于cpu_num),且CPU处于online状态。

  1. 检查CPU是否在线。

    cat /sys/devices/system/cpu/online
  2. 若所绑定的CPU核号不在online列表中,请更换绑定核号,或尝试启用该CPU核。

    例如,执行以下命令,启用CPU1核。

    echo 1 > /sys/devices/system/cpu/cpu1/online
  • 本页导读 (1)
  • 背景介绍
  • 使用限制
  • 使用percpu sqthread特性
  • 启用 percpu sqthread
  • 提交和处理I/O请求
  • 常见问题
  • Q1:创建io_uring时返回错误代码-1(Operation Not Permitted)
  • Q2:创建io_uring时返回错误代码-22(Invalid Parameter)
AI助理

点击开启售前

在线咨询服务

你好,我是AI助理

可以解答问题、推荐解决方案等