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

異步IO框架io_uring實現(xiàn)TCP服務(wù)器的詳細過程

 更新時間:2025年06月24日 09:49:04   作者:Hx__  
io_uring是Linux內(nèi)核的異步I/O模型,解決原生AIO的不足,如減少系統(tǒng)調(diào)用、支持頁緩存、降低數(shù)據(jù)拷貝開銷,通過liburing庫實現(xiàn),安裝需源碼編譯,適用于高IOPS場景,感興趣的朋友跟隨小編一起看看吧

一、io_uring介紹

io_uring是 Linux 于 2019 年加入到內(nèi)核的一種新型異步 I/O 模型,io_uring 主要為了解決 原生AIO(Native AIO) 存在的一些不足之處。下面介紹一下原生 AIO 的不足之處:

  • 系統(tǒng)調(diào)用開銷大:提交 I/O 操作和獲取 I/O 操作的結(jié)果都需要通過系統(tǒng)調(diào)用完成,而觸發(fā)系統(tǒng)調(diào)用時,需求進行上下文切換。在高 IOPS(Input/Output Per Second)的情況下,進行上下文切換也會消耗大量的CPU時間。

  • 僅支持 Direct I/O(直接I/O):在使用原生 AIO 的時候,只能指定 O_DIRECT 標識位(直接 I/O),不能借助文件系統(tǒng)的頁緩存(page cache)來緩存當前的 I/O 請求。

  • 對數(shù)據(jù)有大小對齊限制:所有寫操作的數(shù)據(jù)大小必須是文件系統(tǒng)塊大?。ㄒ话銥?KB)的倍數(shù),而且要與內(nèi)存頁大小對齊。

  • 數(shù)據(jù)拷貝開銷大:每個 I/O 提交需要拷貝 64+8 字節(jié),每個 I/O 完成結(jié)果需要拷貝 32 字節(jié),總共 104 字節(jié)的拷貝。這個拷貝開銷是否可以承受,和單次 I/O 大小有關(guān):如果需要發(fā)送的 I/O 本身就很大,相較之下,這點消耗可以忽略。而在大量小 I/O 的場景下,這樣的拷貝影響比較大。

對應(yīng)io_uring就有他的優(yōu)勢:

  • 減少系統(tǒng)調(diào)用:io_uring通過內(nèi)核態(tài)和用戶態(tài)共享內(nèi)存的方式進行通信。如下圖:

用戶態(tài)和內(nèi)核態(tài)之間通過共享內(nèi)存維護了三部分:提交隊列、完成隊列、提交隊列表項數(shù)組。

提交隊列是一整塊連續(xù)的內(nèi)存空間存儲的環(huán)形隊列,用于存放將要執(zhí)行I/O操作的數(shù)據(jù)。

完成隊列也是一整塊連續(xù)的內(nèi)存空間存儲的環(huán)形隊列,其中存放了I/O操作完成返回的結(jié)果。

提交隊列表項數(shù)組是以數(shù)組形式將要執(zhí)行的I/O操作組織在一起,提交隊列完成隊列分別通過指針指向?qū)?yīng)表項(內(nèi)部通過偏移量實現(xiàn))完成對應(yīng)操作。如下圖所示:

提交隊列具體實現(xiàn)為:io_uring_sq結(jié)構(gòu)體。

struct io_uring_sq {
    unsigned *khead;
    unsigned *ktail;
    unsigned *kflags;
    unsigned *kdropped;
    unsigned *array;
    struct io_uring_sqe *sqes;
?
    unsigned sqe_head;
    unsigned sqe_tail;
?
    size_t ring_sz;
    void *ring_ptr;
?
    unsigned ring_mask;
    unsigned ring_entries;
?
    unsigned pad[2];
};

提交隊列通過struct io_uring_sqe *sqes提交隊列表項數(shù)組,使用khead、ktail指向?qū)?yīng)隊頭和對尾完成應(yīng)用層提交的IO任務(wù)的處理。同理完成隊列也是如此,不過是由內(nèi)核態(tài)將對應(yīng)IO事件執(zhí)行完成后將結(jié)果寫入到對應(yīng)表項。應(yīng)用層通過完成隊列表項即可獲取到最終結(jié)果。

整體流程為:

請求時:1、應(yīng)用創(chuàng)建SQE,更新SQ tail 2、內(nèi)核消費SQE,更新SQ head。內(nèi)核開始處理任務(wù),處理完成后:1、內(nèi)核為完成的一個或多個請求創(chuàng)建CQE,更新CQ tail 2、應(yīng)用層消費CQE,更新CQ head。

二、liburing安裝

上文介紹的io_uring均為內(nèi)核層支持,在內(nèi)核層提供了三個API:

  • io_uring_setup(2)

  • io_uring_register(2)

  • io_uring_enter(2)

    為方便使用直接安裝liburing即可在應(yīng)用層使用io_uring。liburing為作者Axboe封裝好的用戶態(tài)庫。

實驗環(huán)境:vmware 17安裝ubuntu22.04 、內(nèi)核版本:6.8.0-60-generic

選用源碼安裝方式,安裝liburing。

1、獲取源碼:git clone https://github.com/axboe/liburing.git

2、編譯:

cd liburing-master
./configure
make -j
sudo make install

三、代碼實現(xiàn)

#include <stdio.h>
#include <liburing.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
?
#define BUFFER_LENGTH   1024
#define ENTRIES_LENGTH  1024
?
#define EVENT_ACCEPT    0
#define EVENT_READ      1
#define EVENT_WRITE     2
?
// io事件信息
struct req_info{
    int fd;
    int event;
};
?
// 初始化tcp fd
int init_server(unsigned int port){
    int socket_fd = socket(AF_INET, SOCK_STREAM, 0);
    struct sockaddr_in serveraddr;
    memset(&serveraddr, 0, sizeof(struct sockaddr_in));
    serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_port = htons(port);
    if(-1 == bind(socket_fd, (struct sockaddr *)&serveraddr, sizeof(struct sockaddr))){
        perror("bind error!\n");
    }
    listen(socket_fd, 10);
    return socket_fd;
}
?
// 設(shè)置accept事件
int set_event_accept(struct io_uring *ring, int sockfd, struct sockaddr* addr, socklen_t *addrlen, int flags){
    struct io_uring_sqe *sqe = io_uring_get_sqe(ring);
?
    struct req_info accept_info = {
        .fd = sockfd,
        .event = EVENT_ACCEPT
    };
?
    memcpy(&sqe->user_data, &accept_info, sizeof(struct req_info));
    io_uring_prep_accept(sqe, sockfd, addr, addrlen, flags);
?
    return 0;
}
?
// 設(shè)置recv事件
int set_event_recv(struct io_uring *ring, int sockfd, void *buf, size_t len, int flags){
    struct io_uring_sqe *sqe = io_uring_get_sqe(ring);
?
    struct req_info recv_info = {
        .fd = sockfd,
        .event = EVENT_READ
    };
?
    memcpy(&sqe->user_data, &recv_info, sizeof(struct req_info));
    io_uring_prep_recv(sqe, sockfd, buf, len, flags);
?
    return 0;
}
?
// 設(shè)置send事件
int set_event_send(struct io_uring *ring, int sockfd, void *buf, size_t len, int flags){
    struct io_uring_sqe *sqe = io_uring_get_sqe(ring);
?
    struct req_info send_info = {
        .fd = sockfd,
        .event = EVENT_WRITE
    };
?
    memcpy(&sqe->user_data, &send_info, sizeof(struct req_info));
    io_uring_prep_send(sqe, sockfd, buf, len, flags);
?
    return 0;
}
?
int main(int argc, void *argv[]){
    unsigned int port = 9999;
    int sockfd = init_server(port);
?
    struct io_uring_params params;
    memset(&params, 0, sizeof(struct io_uring_params));
    // 初始化io_uring 其中包含了sq和cq
    struct io_uring ring;
?
    io_uring_queue_init_params(ENTRIES_LENGTH, &ring, &params);
?
    struct sockaddr_in clientaddr;
    socklen_t len = sizeof(clientaddr);
    set_event_accept(&ring, sockfd, (struct sockaddr*)&clientaddr, &len, 0);
?
    while(1){
        char buffer[BUFFER_LENGTH] = {0};
?
        // 事件提交
        io_uring_submit(&ring);
?
        // 等待事件完成,其他開發(fā)場景下非必要情況無需等待
        struct io_uring_cqe *cqe;
        io_uring_wait_cqe(&ring, &cqe);
?
        // 獲取完成事件
        struct io_uring_cqe *cqe_list[128];
        int nready = io_uring_peek_batch_cqe(&ring, cqe_list, 128);
        // echo邏輯處理
        for(int i = 0; i < nready; ++i){
            struct io_uring_cqe *entries = cqe_list[i];
            struct req_info result;
            memcpy(&result, &entries->user_data, sizeof(struct req_info));
            if(result.event == EVENT_ACCEPT){
                printf("accept client\n");
                set_event_accept(&ring, sockfd, (struct sockaddr*)&clientaddr, &len, 0);
?
                int connfd = entries->res;
?
                set_event_recv(&ring, connfd, buffer, BUFFER_LENGTH, 0);
            }else if(result.event == EVENT_READ){
                int connfd = entries->res;
                if(connfd == 0){
                    printf("close fd:%d\n", result.fd);
                    close(result.fd);
                }else if(connfd > 0){
                    printf("recv: len:%d, data:%s\n", connfd, buffer);
                    set_event_send(&ring, result.fd, buffer, connfd, 0);
                }else{
                    printf("error recv!\n");
                    close(result.fd);
                }
            }else if(result.event == EVENT_WRITE){
                int ret = entries->res;
                printf("set_event_send ret: %d, %s\n", ret, buffer);
                set_event_recv(&ring, result.fd, buffer, BUFFER_LENGTH, 0);
            }
        }
?
        // 清除完成隊列中完成表項,以免事件重復(fù)處理
        io_uring_cq_advance(&ring, nready);
    }
?
    return 0;
}

更多內(nèi)容可參考:0voice · GitHub 

到此這篇關(guān)于異步IO框架io_uring實現(xiàn)TCP服務(wù)器的文章就介紹到這了,更多相關(guān)io_uring TCP服務(wù)器內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • cwrsync invalid uid nobody 解決方法

    cwrsync invalid uid nobody 解決方法

    這篇文章主要介紹了使用rsync/cwrsync工具進行檔案同步的時候出現(xiàn)invalid uid nobody錯誤的解決方法,需要的朋友可以參考下
    2016-03-03
  • LuLu打造一款macOS的開源防火墻

    LuLu打造一款macOS的開源防火墻

    LuLu是一款macOS下的免費且開源防火墻 ,其主要用于阻止未經(jīng)授權(quán)的(傳出)網(wǎng)絡(luò)流量,除非用戶明確允許,下面通過本文給大家分享通過LuLu打造一款macOS的開源防火墻功能,一起看看吧
    2018-03-03
  • linux 自動化運維工具ansible的使用詳細教程

    linux 自動化運維工具ansible的使用詳細教程

    這篇文章主要介紹了自動化運維工具ansible的使用詳細教程的相關(guān)資料,需要的朋友可以參考下
    2016-02-02
  • 云服務(wù)器(Linux)安裝部署Kafka的詳細過程

    云服務(wù)器(Linux)安裝部署Kafka的詳細過程

    這篇文章主要介紹了云服務(wù)器(Linux)安裝部署Kafka的詳細過程,kafka的安裝需要依賴于jdk,需要在服務(wù)器上提前安裝好該環(huán)境,這里使用用jdk1.8,本文給大家詳細介紹感興趣的朋友跟隨小編一起看看吧
    2022-11-11
  • 深入解析Apache?Hudi內(nèi)核文件標記機制

    深入解析Apache?Hudi內(nèi)核文件標記機制

    這篇文章主要為大家介紹了深入解析Apache?Hudi內(nèi)核文件標記機制,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步早日升職加薪
    2022-03-03
  • 在Windows上搭建自己的Git服務(wù)器的圖文教程

    在Windows上搭建自己的Git服務(wù)器的圖文教程

    這篇文章主要為大家詳細介紹了如何在 Windows10 Professional 服務(wù)器上搭建自己的 Git 服務(wù)器,文中通過圖文詳細的介紹了搭建步驟,需要的可以參考下
    2023-08-08
  • RHEL網(wǎng)絡(luò)服務(wù)器詳解

    RHEL網(wǎng)絡(luò)服務(wù)器詳解

    這篇文章主要介紹了RHEL網(wǎng)絡(luò)服務(wù)器的相關(guān)知識,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2023-12-12
  • 教你使用Ubuntu搭建DNS服務(wù)器

    教你使用Ubuntu搭建DNS服務(wù)器

    這篇文章主要介紹了Ubuntu搭建DNS服務(wù)器,本例是在ubuntu18.04上進行的,其他版本的ubuntu同樣類似,重點講解了/etc/bind/named.conf.options配置文件,需要的朋友可以參考下
    2022-09-09
  • NATS服務(wù)器配置的詳細介紹

    NATS服務(wù)器配置的詳細介紹

    這篇文章主要介紹了NATS服務(wù)器配置的詳細介紹的相關(guān)資料,希望通過本文能幫助到大家,需要的朋友可以參考下
    2017-10-10
  • 深入理解微服務(wù)中的高并發(fā)、高性能、高可用及處理方式

    深入理解微服務(wù)中的高并發(fā)、高性能、高可用及處理方式

    這篇文章主要介紹了深入理解微服務(wù)中的高并發(fā)、高性能、高可用及處理方式,系統(tǒng)在巨大的流量洪峰(即指高并發(fā)場景)沖擊下,依然能高效、穩(wěn)定、正常地(即指高性能、高可用)對外提供服務(wù),這是系統(tǒng)設(shè)計的主要目標之一,需要的朋友可以參考下
    2023-10-10

最新評論

宜章县| 靖远县| 视频| 屯留县| 汕头市| 定西市| 德保县| 翁牛特旗| 清水河县| 驻马店市| 若羌县| 铁力市| 泌阳县| 江门市| 枣庄市| 兰西县| 昆山市| 沁水县| 大庆市| 昭苏县| 崇文区| 临澧县| 赤水市| 洛宁县| 乐山市| 托克逊县| 天镇县| 宣城市| 镇宁| 钦州市| 三亚市| 淳安县| 拉萨市| 西充县| 高碑店市| 遂川县| 集安市| 大悟县| 阿城市| 易门县| 玉林市|