首页 > 其他分享 >io_uring

io_uring

时间:2024-03-29 19:24:38浏览次数:18  
标签:请求 int uring fd 内核 io

目录


概述

io_uring 是 Linux 内核中实现的一个高效异步 I/O 框架,其实现原理基于事件驱动和用户空间与内核空间之间的高效数据交换。以下是 io_uring 实现原理的简要概述:

  1. 数据结构
    io_uring 主要由两个环形缓冲区(rings)构成:提交队列(SQ, Submit Queue)和完成队列(CQ, Completion Queue)。这两个队列都位于内核空间,但可以从用户空间直接访问,通常通过内存映射(mmap)实现。

    • 提交队列(SQ):用于存放用户空间提交的 I/O 请求。用户空间程序将 I/O 请求填充到 SQ 中,并通知内核有新的请求需要处理。
    • 完成队列(CQ):用于存放已经完成的 I/O 请求。内核在处理完 I/O 请求后,会将结果填充到 CQ 中,并通知用户空间有请求已完成。
  2. 工作流程

    • 初始化:用户空间程序通过 io_uring_setup() 系统调用创建 io_uring 实例,并设置相关参数,如队列的大小等。
    • 提交请求:用户空间程序将 I/O 请求(如读、写等)填充到 SQ 中,并通过原子操作更新 SQ 的头部指针来通知内核有新的请求。
    • 内核处理:内核定期检查 SQ,发现有新的请求后,将其从 SQ 中取出并进行处理。处理过程中可能涉及磁盘操作、网络通信等实际的 I/O 操作。
    • 完成通知:当 I/O 请求完成后,内核将结果填充到 CQ 中,并通过更新 CQ 的相关指针或发送事件通知来告知用户空间有请求已完成。
    • 用户空间处理完成请求:用户空间程序定期检查 CQ,发现有请求完成后,从 CQ 中取出结果并进行后续处理。
  3. 异步性和非阻塞性
    io_uring 的关键优势在于其异步性和非阻塞性。用户空间程序在提交请求后可以继续执行其他任务,而不必等待 I/O 请求的完成。当 I/O 请求完成后,内核会通过事件通知机制(如 io_uring_enter() 系统调用的非阻塞模式或通过设置文件描述符的 POLL_IN 事件)来告知用户空间程序。

  4. 批量处理
    为了提高效率,io_uring 支持批量提交和处理请求。用户空间程序可以一次性将多个 I/O 请求提交到 SQ 中,内核也可以批量地从 SQ 中取出请求进行处理,并将完成的结果批量地填充到 CQ 中。

  5. 灵活性和可扩展性
    io_uring 提供了灵活的 API 和丰富的功能,可以支持不同类型的 I/O 操作和各种应用场景。同时,由于其基于事件驱动和高效的数据交换机制,io_uring 具有良好的可扩展性,可以随着系统资源的增加而线性地提高性能。

总的来说,io_uring 的实现原理基于高效的环形缓冲区、事件驱动和用户空间与内核空间之间的直接数据交换,为 Linux 系统提供了强大而灵活的异步 I/O 能力。


常用函数

io_uring 在 Linux 中为异步 I/O 提供了强大的支持,它包含了一系列的函数来初始化、配置、提交和获取 I/O 操作。以下是一些 io_uring 中常用的函数及其用法的详细介绍:

  1. io_uring_setup()

    • 功能:用于初始化和配置 io_uring 环境。
    • 原型int io_uring_setup(unsigned entries, struct io_uring_params *p);
      • entries:指定 io_uring 的入口数目,即同时处理的 I/O 事件数目。
      • p:指向 struct io_uring_params 结构的指针,用于传递其他配置参数。
    • 返回值:成功时返回一个新的文件描述符,用于后续的 I/O 操作。
  2. io_uring_enter()

    • 功能:用于提交 I/O 事件并等待其完成。
    • 原型int io_uring_enter(int fd, unsigned to_submit, unsigned min_complete, unsigned flags, sigset_t *sig);
      • fdio_uring 文件描述符,由 io_uring_setup() 返回。
      • to_submit:要提交的 I/O 事件数量。
      • min_complete:函数返回前必须完成的最小事件数量。
      • flags:用于控制函数行为的标志位。
      • sig:指向信号集的指针,用于在 I/O 完成时接收信号。
    • 返回值:已完成的 I/O 事件数量。
  3. io_uring_register()

    • 功能:用于注册内核用户共享缓冲区,如文件描述符、缓冲区等。
    • 原型int io_uring_register(unsigned int fd, unsigned int opcode, void *arg, unsigned int nr_args);
      • fdio_uring 文件描述符。
      • opcode:指定注册操作的类型。
      • arg:指向要注册的数据的指针。
      • nr_args:指定 arg 指针指向的数据的大小或数量。
    • 返回值:成功时返回 0,失败时返回负的错误码。
  4. io_uring_unregister()

    • 功能:用于取消之前通过 io_uring_register() 注册的资源。
    • 用法:类似于 io_uring_register(),但用于注销资源。
  5. io_uring_prep_*() 和 io_uring_submit()

    • 这是一系列函数,用于准备和提交各种类型的 I/O 操作,如读、写、轮询等。例如:
      • io_uring_prep_readv():准备读取操作。
      • io_uring_prep_writev():准备写入操作。
      • io_uring_prep_poll_add():注册一个轮询事件。
    • 用法:首先使用 io_uring_prep_*() 函数准备 I/O 操作,然后使用 io_uring_submit() 提交这些操作到 io_uring 中进行处理。
  6. io_uring_wait_cqe() 和 io_uring_peek_cqe()

    • 这两个函数用于等待和查看完成队列事件(CQE)。
      • io_uring_wait_cqe():等待一个 CQE 被填充,并返回该 CQE 的指针。
      • io_uring_peek_cqe():查看最早生成的未处理 CQE 的指针,但不将其从完成队列(CQ)中弹出。

这些函数提供了对 io_uring 功能的全面访问,使得开发者能够高效地执行异步 I/O 操作并优化系统性能。在使用这些函数时,建议查阅最新的 Linux 内核文档以获取更详细的信息和示例代码。


示例

当然,以下是一个简单的 io_uring 使用示例,并说明其使用场景。

示例代码

假设我们要使用 io_uring 来异步地读取一个文件的内容。以下是一个简化的示例代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <liburing.h>

#define QUEUE_DEPTH  10
#define BLOCK_SIZE   4096

int main(int argc, char *argv[]) {
    struct io_uring ring;
    struct io_uring_sqe *sqe;
    struct io_uring_cqe *cqe;
    char buffer[BLOCK_SIZE];
    int fd, ret;

    if (argc != 2) {
        fprintf(stderr, "Usage: %s <filename>\n", argv[0]);
        return 1;
    }

    fd = open(argv[1], O_RDONLY);
    if (fd < 0) {
        perror("open");
        return 1;
    }

    ret = io_uring_queue_init(QUEUE_DEPTH, &ring, 0);
    if (ret) {
        fprintf(stderr, "io_uring_queue_init: %d\n", ret);
        close(fd);
        return 1;
    }

    sqe = io_uring_get_sqe(&ring);
    io_uring_prep_read(sqe, fd, buffer, BLOCK_SIZE, 0);

    ret = io_uring_submit(&ring);
    if (ret <= 0) {
        fprintf(stderr, "io_uring_submit: %d\n", ret);
        goto cleanup;
    }

    ret = io_uring_wait_cqe(&ring, &cqe);
    if (ret < 0) {
        fprintf(stderr, "io_uring_wait_cqe: %d\n", ret);
        goto cleanup;
    }

    printf("Read %d bytes\n", cqe->res);
    // 这里可以处理读取到的数据,例如打印出来或进行其他处理。

    io_uring_cqe_seen(&ring, cqe);

cleanup:
    io_uring_queue_exit(&ring);
    close(fd);
    return 0;
}

使用场景说明

  1. 高并发 I/O:当系统需要处理大量并发的 I/O 请求时,io_uring 提供了高效的异步 I/O 机制。例如,在 Web 服务器、数据库或存储系统中,可能有成千上万的并发连接,每个连接都可能发起 I/O 请求。使用 io_uring 可以显著提高这些系统的吞吐量和响应速度。
  2. 资源优化:传统的同步 I/O 模型在处理 I/O 请求时会阻塞调用线程,导致 CPU 资源浪费。而 io_uring 的异步特性允许线程在等待 I/O 完成时继续执行其他任务,从而更有效地利用 CPU 资源。
  3. 低延迟应用:对于需要快速响应的应用,如实时分析、高频交易等,io_uring 可以提供较低的延迟和更高的吞吐量。通过减少上下文切换和系统调用的开销,它可以更快地处理 I/O 请求并返回结果。
  4. 可扩展性io_uring 的设计考虑了可扩展性,可以随着 CPU 核心数的增加而线性扩展性能。这使得它非常适合处理不断增长的 I/O 负载,而无需对代码进行大量修改或优化。
  5. 灵活性io_uring 提供了一个通用的 I/O 框架,支持多种类型的 I/O 操作和标志。这使得开发者能够根据需要灵活地调整 I/O 行为,以满足不同的应用需求。

标签:请求,int,uring,fd,内核,io
From: https://www.cnblogs.com/yubo-guan/p/18104456

相关文章

  • kingbaseES V8R6集群运维案例之---配置priority防止failover切换案例
    案例说明:在一主多备的架构中,需要配置一台备库在主备切换时,不能选举为主库。对于repmgr主备切换主库的选择算法如下:Tips:Repmgr选举候选备节点会以以下顺序选举:LSN---->Priority---->Node_ID。系统会先选举一个LSN比较大者作为候选备节点;如LSN一样,会根据Priority优先级进行比......
  • nbtstat /?命令参数 显示使用NBT(NetBIOS over TCP/IP)的协议统计信息和当前TCP/IP连接
    NBTSTAT(NetBIOSoverTCP/IPStatistics)是一个用于显示和更新NetBIOS名称缓存、NetBIOS名称表和NetBIOS会话表的Windows命令行实用程序。它允许用户查看当前网络上的NetBIOS名称信息,以便诊断网络连接问题和执行基本的网络故障排除。NetBIOS是一种用于在局域网中进行通信的协议,它......
  • ios使用openlayer地图缩放时卡顿
    问题描述h5项目使用openlayer展示地图,并且使用VectorLayer铺点,安卓完全没问题,但是ios上缩放后会突然触发无法缩放并且无法点击拖动缓慢等问题。经排查,是VectorLayer的minZoommaxZoom导致,但不理解原因。问题代码如下importVectorLayerfrom'ol/layer/Vector'vectorLayer......
  • 【前端】使用Web Audio API 技术播放音乐
    简言记录下使用webaudio播放音乐的方法。WebAudioAPIWebAudioAPI提供了在Web上控制音频的一个非常有效通用的系统,允许开发者来自选音频源,对音频添加特效,使音频可视化,添加空间效果(如平移),等等。你可以先看下api接口介绍文章WebAudioAPI接口介绍。html的<au......
  • AWS Solutions Architect - Prep
    What'sAWSS3databaseforunstructureddata,wecanputastaticwebsite(doesn'tneedthatmuchback-end)onS3WhyuseS3highscalabilityhorizontalscaling:storagedoesn'tfulfilltheneed,thenjustusemoredevicesverticalscali......
  • vuex.esm.js:135 Uncaught Error: [vuex] getters should be function but “getters.
    报错vuex.esm.js:135UncaughtError:[vuex]gettersshouldbefunctionbut"getters.mode"inmodule"userModule"is"dark".atassert(vuex.esm.js:135:1)原因:在使用vuex的moulds时index.js中已创建了一个vue实例newVuex.Store,在模块文件中又再创建了一个,导致报......
  • 详解DROO论文中的order-preserving quantization method(保序量化方法)
    ​一、论文概述1.原文GitHub链接DeepReinforcementLearningforOnlineComputationOffloadinginWirelessPoweredMobile-EdgeComputingNetworks2.原文大意提出了一种深度强化学习方法解决了边缘计算任务卸载决策和资源分配问题。整体分为两大部分:其中第一部......
  • Visual Studio Code & Python教程1简介
    1简介VisualStudioCode是一款开源代码编辑器,可免费使用,完全支持Python编程语言的开发。它具有一些有用的功能,例如与世界各地的其他程序员进行实时协作。本章旨在介绍VSCode,帮助您了解其开发过程及其不同组件。我们将讨论为什么它可能是最受欢迎的代码编辑器,了解它的功能,并讨......
  • A Systematic Survey of Prompt Engineering in Large Language Models: Techniques a
    本文是LLM系列文章,针对《ASystematicSurveyofPromptEngineeringinLargeLanguageModels:TechniquesandApplications》的翻译。大型语言模型中提示工程的系统综述:技术与应用摘要1引言2提示工程3结论摘要提示工程已经成为扩展大型语言模型(LLM)和视......
  • Large Language Models As Evolution Strategies
    本文是LLM系列文章,针对《LargeLanguageModelsAsEvolutionStrategies》的翻译。作为进化策略的大型语言模型摘要1引言2相关工作3背景4将LLMS转化为ES算法5LLMS作为零样本进化策略6EVOLLM消融研究7EVOLLM与教师微调8讨论摘要大型Transformer模......