最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++ io_uring的使用小結(jié)

 更新時間:2026年01月11日 15:18:47   作者:令狐掌門  
io_uring 是 Linux 內(nèi)核在 5.1 版本引入的一套全新的、高性能的異步 I/O  接口,本文就來詳細的介紹一下C++ io_uring的使用小結(jié),感興趣的可以了解一下

io_uring 是 Linux 內(nèi)核在 5.1 版本引入的一套全新的、高性能的異步 I/O (Asynchronous I/O) 接口。它的出現(xiàn)是為了解決舊有的 epolllinux-aio 在面對現(xiàn)代高速存儲設備(如 NVMe SSD)和高并發(fā)網(wǎng)絡場景時的性能瓶頸。

雖然 io_uring 是一個 C 語言的內(nèi)核 API,但在 C++ 高性能網(wǎng)絡編程和存儲編程中,它正逐漸成為主流選擇。

以下是對 C++ io_uring 的詳細介紹,包括其原理、優(yōu)勢以及如何在 C++ 中使用它。

1. 為什么我們需要 io_uring?

io_uring 出現(xiàn)之前,Linux 下主要有兩種 I/O 模式:

  1. 同步 I/O (read/write) + 多路復用 (epoll):
    • 這是最主流的網(wǎng)絡編程模式(如 Nginx, Redis, Node.js)。
    • 缺點: read/write 是系統(tǒng)調(diào)用,每次調(diào)用都需要在用戶態(tài)和內(nèi)核態(tài)之間切換。對于海量小包處理,系統(tǒng)調(diào)用的開銷非常大。此外,epoll 只能通知“可讀/可寫”狀態(tài),實際的數(shù)據(jù)拷貝還是同步發(fā)生的。
  2. Linux Native AIO (libaio):
    • 缺點: 僅支持 Direct I/O (O_DIRECT),對 Buffered I/O 支持很差(經(jīng)常退化為同步阻塞)。API 設計復雜,且存在不必要的內(nèi)存拷貝。

io_uring 的目標: 提供統(tǒng)一的、全異步的、零拷貝(或少拷貝)的、無鎖的 I/O 接口,既支持文件 I/O 也支持網(wǎng)絡 I/O。

2. io_uring 的核心原理:環(huán)形緩沖區(qū) (Ring Buffer)

io_uring 的名字來源于 “User Ring”。它在用戶態(tài)和內(nèi)核態(tài)之間共享了兩個環(huán)形隊列(Ring Buffer),從而避免了頻繁的系統(tǒng)調(diào)用和內(nèi)存拷貝。

這兩個隊列分別是:

  1. 提交隊列 (Submission Queue, SQ):
    • 用戶程序向這個隊列中放入 I/O 請求(稱為 SQE, Submission Queue Entry)。
    • 例如:“請把文件 A 的前 4KB 讀取到緩沖區(qū) B”。
  2. 完成隊列 (Completion Queue, CQ):
    • 內(nèi)核處理完請求后,將結(jié)果(稱為 CQE, Completion Queue Entry)放入這個隊列。
    • 用戶程序從這里讀取結(jié)果(例如:“讀取成功,讀取了 4096 字節(jié)”)。

工作流程:

  1. 用戶將 SQE 放入 SQ。
  2. 用戶通過一次系統(tǒng)調(diào)用 (io_uring_enter) 通知內(nèi)核(或者在輪詢模式下甚至不需要系統(tǒng)調(diào)用)。
  3. 內(nèi)核從 SQ 獲取請求并執(zhí)行。
  4. 內(nèi)核將結(jié)果寫入 CQ。
  5. 用戶從 CQ 讀取結(jié)果。

3. C++ 中使用 io_uring (liburing)

直接操作內(nèi)核的原始結(jié)構(gòu)體非常繁瑣且容易出錯。因此,通常使用官方封裝的 C 庫 liburing。在 C++ 中,我們通常直接調(diào)用 liburing 的 C 接口,或者使用對其進行 C++ 封裝的庫(如 asio 的 io_uring backend)。

下面是一個使用 liburing 進行異步文件讀取的 C++ 示例。

前置準備

你需要安裝 liburing 開發(fā)庫:

# Ubuntu/Debian
sudo apt install liburing-dev

完整代碼示例

這個例子展示了如何異步讀取一個文件的前 1024 個字節(jié)。

#include <iostream>
#include <fcntl.h>
#include <unistd.h>
#include <cstring>
#include <liburing.h>
#include <sys/stat.h>

// 定義隊列深度,即環(huán)形緩沖區(qū)的大小
#define QUEUE_DEPTH 8
#define BLOCK_SZ    1024

int main() {
    // 1. 初始化 io_uring 結(jié)構(gòu)
    struct io_uring ring;
    // io_uring_queue_init(深度, 實例指針, 標志位)
    // 0 表示默認配置
    int ret = io_uring_queue_init(QUEUE_DEPTH, &ring, 0);
    if (ret < 0) {
        std::cerr << "io_uring_queue_init failed: " << -ret << std::endl;
        return 1;
    }

    // 2. 打開文件 (使用 O_DIRECT 通常能發(fā)揮 io_uring 最大性能,但這里為了簡單使用普通模式)
    // 注意:實際項目中請確保文件存在,或者創(chuàng)建一個測試文件
    int fd = open("test.txt", O_RDONLY);
    if (fd < 0) {
        // 如果文件不存在,創(chuàng)建一個臨時的
        fd = open("test.txt", O_RDWR | O_CREAT, 0644);
        const char* msg = "Hello from io_uring! This is a test file content.";
        write(fd, msg, strlen(msg));
        fsync(fd);
        lseek(fd, 0, SEEK_SET); // 重置文件指針
    }

    // 準備緩沖區(qū)
    char buffer[BLOCK_SZ];
    memset(buffer, 0, BLOCK_SZ);
    struct iovec iov;
    iov.iov_base = buffer;
    iov.iov_len = BLOCK_SZ;

    // 3. 獲取一個提交隊列項 (SQE)
    struct io_uring_sqe *sqe = io_uring_get_sqe(&ring);
    if (!sqe) {
        std::cerr << "Could not get SQE" << std::endl;
        return 1;
    }

    // 4. 填充 SQE 請求
    // 這是一個 "Read Vector" 操作
    // 參數(shù): sqe, 文件描述符, iovec數(shù)組, iovec數(shù)量, 偏移量
    io_uring_prep_readv(sqe, fd, &iov, 1, 0);
    
    // 設置用戶數(shù)據(jù) (user_data),這是一個 64 位字段,內(nèi)核會原樣傳回 CQE。
    // 通常用來存放請求的 ID 或者回調(diào)函數(shù)的指針。
    io_uring_sqe_set_data(sqe, nullptr); // 這里簡單設為 null

    // 5. 提交請求給內(nèi)核
    // io_uring_submit 會調(diào)用系統(tǒng)調(diào)用 io_uring_enter
    ret = io_uring_submit(&ring);
    if (ret < 0) {
        std::cerr << "io_uring_submit failed: " << -ret << std::endl;
        return 1;
    }

    std::cout << "Request submitted, waiting for completion..." << std::endl;

    // 6. 等待完成隊列項 (CQE)
    struct io_uring_cqe *cqe;
    // io_uring_wait_cqe 會阻塞直到至少有一個事件完成
    ret = io_uring_wait_cqe(&ring, &cqe);
    if (ret < 0) {
        std::cerr << "io_uring_wait_cqe failed: " << -ret << std::endl;
        return 1;
    }

    // 7. 處理結(jié)果
    if (cqe->res < 0) {
        std::cerr << "Async read failed: " << -cqe->res << std::endl;
    } else {
        std::cout << "Read " << cqe->res << " bytes." << std::endl;
        std::cout << "Content: " << buffer << std::endl;
    }

    // 8. 標記 CQE 已處理 (這一步很重要,否則隊列會滿)
    io_uring_cqe_seen(&ring, cqe);

    // 9. 清理資源
    close(fd);
    io_uring_queue_exit(&ring);

    return 0;
}

代碼編譯

g++ -o uring_test uring_test.cpp -luring

4. io_uring 的高級特性

對于追求極致性能的 C++ 開發(fā)者,io_uring 提供了幾個殺手級特性:

A. Submission Queue Polling (SQPOLL)

默認情況下,io_uring_submit 仍然需要一次系統(tǒng)調(diào)用 (io_uring_enter) 來通知內(nèi)核有新任務。
如果在初始化時設置 IORING_SETUP_SQPOLL 標志,內(nèi)核會啟動一個專門的內(nèi)核線程來輪詢 SQ。

  • 效果: 用戶只需把 SQE 放入環(huán)形隊列,內(nèi)核線程自動發(fā)現(xiàn)并處理。完全消除了系統(tǒng)調(diào)用開銷。
  • 代價: 消耗更多的 CPU 資源(內(nèi)核線程一直在空轉(zhuǎn)檢查)。

B. 注冊文件和緩沖區(qū) (Registered Files/Buffers)

在傳統(tǒng)的系統(tǒng)調(diào)用中,每次操作內(nèi)核都需要把文件描述符 (fd) 映射到內(nèi)部的文件結(jié)構(gòu),并鎖定內(nèi)存頁。

  • Registered Files: 預先將 fd 數(shù)組注冊給 io_uring,后續(xù)請求直接使用索引,減少內(nèi)核查找 fd 的開銷。
  • Registered Buffers: 預先將用戶態(tài)內(nèi)存鎖定并映射,避免每次 I/O 時內(nèi)核重復進行 get_user_pages 操作。

C. 鏈接請求 (IOSQE_IO_LINK)

你可以將多個 SQE 鏈接起來,強制它們按順序執(zhí)行。例如:先 open 文件,成功后再 read,最后 close。這允許在一次系統(tǒng)調(diào)用中編排復雜的 I/O 邏輯。

5. C++ 生態(tài)中的 io_uring

雖然可以直接使用 liburing,但在現(xiàn)代 C++ 開發(fā)中,我們通常使用更高層的封裝:

  1. Boost.Asio:

    • Boost.Asio 已經(jīng)支持 io_uring 作為底層的 Reactor 實現(xiàn)(在 Linux 上)。
    • 通過 BOOST_ASIO_HAS_IO_URING 宏啟用。這使得你可以在不改變現(xiàn)有 Asio 代碼邏輯的情況下,享受到 io_uring 的性能提升。
  2. Seastar:

    • 一個高性能的 C++ futures 框架,專為現(xiàn)代硬件設計。它是 io_uring 的早期采用者,非常適合構(gòu)建高吞吐量的網(wǎng)絡服務。
  3. Userver:

    • Yandex 開源的 C++ 異步框架,底層也深度集成了 io_uring。

6. io_uring vs Epoll 性能對比

  • 小包/高頻 I/O: io_uring 優(yōu)勢巨大。因為減少了系統(tǒng)調(diào)用次數(shù),上下文切換開銷大幅降低。
  • 大包/低頻 I/O: 差距較小,瓶頸主要在內(nèi)存拷貝和硬件帶寬。
  • Spectre/Meltdown 補丁影響: 這些 CPU 漏洞補丁增加了系統(tǒng)調(diào)用的開銷,因此 io_uring(尤其是 SQPOLL 模式)在受補丁影響的機器上優(yōu)勢更明顯。

7. 總結(jié)

C++ io_uring 是 Linux 高性能編程的未來。

  • 核心優(yōu)勢: 真正的異步 I/O、減少系統(tǒng)調(diào)用、減少內(nèi)存拷貝、統(tǒng)一了網(wǎng)絡和磁盤 I/O 接口。
  • 適用場景: 高并發(fā)網(wǎng)絡服務器(HTTP/RPC)、高性能數(shù)據(jù)庫、分布式存儲系統(tǒng)。
  • 建議: 如果你在編寫通用的業(yè)務代碼,建議使用 Boost.Asio 等封裝好的庫;如果你在開發(fā)底層的存儲引擎或極致性能的網(wǎng)關(guān),深入學習并直接使用 liburing 是非常有價值的。

到此這篇關(guān)于C++ io_uring的使用小結(jié)的文章就介紹到這了,更多相關(guān)C++ io_uring內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C語言實現(xiàn)字符串匹配KMP算法

    C語言實現(xiàn)字符串匹配KMP算法

    相信很多人(包括自己)初識KMP算法的時候始終是丈二和尚摸不著頭腦,要么完全不知所云,要么看不懂書上的解釋,要么自己覺得好像心里了解KMP算法的意思,卻說不出個究竟,所謂知其然不知其所以然是也。
    2014-08-08
  • C++命名空間?缺省參數(shù)?const總結(jié)?引用總結(jié)?內(nèi)聯(lián)函數(shù)?auto關(guān)鍵字詳解

    C++命名空間?缺省參數(shù)?const總結(jié)?引用總結(jié)?內(nèi)聯(lián)函數(shù)?auto關(guān)鍵字詳解

    這篇文章主要介紹了C++命名空間?缺省參數(shù)?const總結(jié)?引用總結(jié)?內(nèi)聯(lián)函數(shù)?auto關(guān)鍵字詳解的相關(guān)資料,需要的朋友可以參考下
    2023-01-01
  • C++11模板元編程-std::enable_if示例詳解

    C++11模板元編程-std::enable_if示例詳解

    這篇文章主要給大家介紹了關(guān)于C++11模板元編程-std::enable_if的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-10-10
  • C++實現(xiàn)反轉(zhuǎn)鏈表的兩種方法

    C++實現(xiàn)反轉(zhuǎn)鏈表的兩種方法

    本文主要介紹了C++實現(xiàn)反轉(zhuǎn)鏈表的兩種方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-02-02
  • ubuntu修改gcc版本的操作方法

    ubuntu修改gcc版本的操作方法

    今天小編就為大家分享一篇ubuntu修改gcc版本的操作方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-12-12
  • C語言小程序 楊輝三角示例代碼

    C語言小程序 楊輝三角示例代碼

    輸入要顯示的楊輝三角的行數(shù),會打印出金字塔型的楊輝三角,不過行數(shù)太多的話,效果不太好,可以再調(diào)整一下格式控制
    2013-07-07
  • C語言實現(xiàn)倉庫物資管理系統(tǒng)

    C語言實現(xiàn)倉庫物資管理系統(tǒng)

    這篇文章主要為大家詳細介紹了C語言實現(xiàn)倉庫物資管理系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-12-12
  • C++中const與#define的利弊分析

    C++中const與#define的利弊分析

    C++中不但可以用define定義常量還可以用const定義常量,下面這篇文章主要給大家分析介紹了關(guān)于C++中const與#define的利弊,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2018-05-05
  • C語言實現(xiàn)醫(yī)院管理系統(tǒng)

    C語言實現(xiàn)醫(yī)院管理系統(tǒng)

    這篇文章主要為大家詳細介紹了C語言實現(xiàn)醫(yī)院管理系統(tǒng),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-12-12
  • C語言中#pragma預處理指令的使用

    C語言中#pragma預處理指令的使用

    在所有的預處理指令中,#pragma指令可能是最復雜的了,它的作用是設定編譯器的狀態(tài)或者是指示編譯器完成一些特定的動作,本文主要介紹了C語言中#pragma預處理指令的使用,感興趣的可以了解一下
    2023-12-12

最新評論

大方县| 绥德县| 通化市| 荔浦县| 沾化县| 西畴县| 龙陵县| 会泽县| 永吉县| 界首市| 原阳县| 郎溪县| 白城市| 石门县| 唐河县| 防城港市| 湖州市| 广东省| 武夷山市| 当雄县| 北安市| 化德县| 渝北区| 永州市| 新竹市| 聂荣县| 漾濞| 郎溪县| 南丹县| 东至县| 北宁市| 和政县| 铜梁县| 肥西县| 交城县| 邮箱| 荆门市| 昭平县| 曲周县| 蓬溪县| 潞西市|