• linux新版本io框架 io_uring


    从别的博主那copy过来:

    1 io_uring是Linux内核的一个新型I/O事件通知机制,具有以下特点:
    高性能:相比传统的select/poll/epoll等I/O多路复用机制,io_uring采用了更高效的ring buffer实现方式,可以在处理大量并发I/O请求时提供更高的吞吐量和低延迟。

    异步:io_uring支持异步I/O操作,并且可以通过用户空间和内核空间之间的共享内存映射来避免数据拷贝,从而减少了CPU的开销。

    事件批处理:io_uring可以将多个I/O操作合并成一个请求进行处理,从而降低了系统调用的次数和上下文切换的开销。

    灵活性:io_uring提供了非常灵活的接口和配置选项,可以根据应用程序的需要进行优化和调整。同时,它还支持多线程操作和信号驱动I/O等功能。

    2 安装
    确认系统内核是5.10以后的版本,还需安装liburing(依赖于内核的三个新的系统调用
    io_uring_setup io_uring_register io_uring_enter )
    安装liburing库,它对内核三个新的系统进行了封装
    git clone https://github.com/axboe/liburing.git
    cd liburing/
    ./configure
    make && make install

    由于github上不去 

    找了一个国内的源
    git clone https://gitee.com/anolis/liburing.git
     

    make install 可以看到  将 liburing.h 和静态库 动态库copy到了 系统目录

     写一个测试程序  

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. #define ENTRIES_LENGTH 1024
    9. enum {
    10. EVENT_ACCEPT = 0,
    11. EVENT_READ,
    12. EVENT_WRITE
    13. };
    14. typedef struct _conninfo {
    15. int connfd;
    16. int event;
    17. } conninfo;
    18. // sizeof(conninfo) = 8
    19. // 0, 1, 2
    20. // 3, 4, 5
    21. void set_send_event(struct io_uring *ring, int sockfd, void *buf, size_t len, int flags) {
    22. struct io_uring_sqe *sqe = io_uring_get_sqe(ring);
    23. io_uring_prep_send(sqe, sockfd, buf, len, flags);
    24. conninfo info_send = {
    25. .connfd = sockfd,
    26. .event = EVENT_WRITE,
    27. };
    28. memcpy(&sqe->user_data, &info_send, sizeof(info_send));
    29. }
    30. void set_recv_event(struct io_uring *ring, int sockfd, void *buf, size_t len, int flags) {
    31. struct io_uring_sqe *sqe = io_uring_get_sqe(ring);
    32. io_uring_prep_recv(sqe, sockfd, buf, len, flags);
    33. conninfo info_recv = {
    34. .connfd = sockfd,
    35. .event = EVENT_READ,
    36. };
    37. memcpy(&sqe->user_data, &info_recv, sizeof(info_recv));
    38. }
    39. void set_accept_event(struct io_uring *ring, int sockfd, struct sockaddr *addr,
    40. socklen_t *addrlen, int flags) {
    41. struct io_uring_sqe *sqe = io_uring_get_sqe(ring);
    42. io_uring_prep_accept(sqe, sockfd, addr, addrlen, flags);
    43. conninfo info_accept = {
    44. .connfd = sockfd,
    45. .event = EVENT_ACCEPT,
    46. };
    47. memcpy(&sqe->user_data, &info_accept, sizeof(info_accept));
    48. }
    49. int main() {
    50. int sockfd = socket(AF_INET, SOCK_STREAM, 0); // io
    51. struct sockaddr_in servaddr;
    52. memset(&servaddr, 0, sizeof(struct sockaddr_in)); // 192.168.2.123
    53. servaddr.sin_family = AF_INET;
    54. servaddr.sin_addr.s_addr = htonl(INADDR_ANY); // 0.0.0.0
    55. servaddr.sin_port = htons(9999);
    56. if (-1 == bind(sockfd, (struct sockaddr*)&servaddr, sizeof(struct sockaddr))) {
    57. printf("bind failed: %s", strerror(errno));
    58. return -1;
    59. }
    60. listen(sockfd, 10);
    61. //liburing
    62. struct io_uring_params params;
    63. memset(¶ms, 0, sizeof(params));
    64. struct io_uring ring;
    65. io_uring_queue_init_params(ENTRIES_LENGTH, &ring, ¶ms);
    66. struct io_uring_sqe *sqe = io_uring_get_sqe(&ring);
    67. struct sockaddr_in clientaddr;
    68. socklen_t clilen = sizeof(struct sockaddr);
    69. set_accept_event(&ring, sockfd, (struct sockaddr*)&clientaddr, &clilen, 0);
    70. char buffer[1024] = {0};
    71. while (1) {
    72. io_uring_submit(&ring);
    73. struct io_uring_cqe *cqe;
    74. io_uring_wait_cqe(&ring, &cqe);
    75. struct io_uring_cqe *cqes[10];
    76. int cqecount = io_uring_peek_batch_cqe(&ring, cqes, 10);
    77. //printf("cqecount --> %d\n", cqecount);
    78. int i = 0;
    79. for (i = 0;i < cqecount;i ++) {
    80. cqe = cqes[i];
    81. conninfo ci;
    82. memcpy(&ci, &cqe->user_data, sizeof(ci));
    83. if (ci.event == EVENT_ACCEPT) { // recv/send
    84. if (cqe->res < 0) continue;
    85. int connfd = cqe->res;
    86. //printf("accept --> %d\n", connfd);
    87. set_accept_event(&ring, ci.connfd, (struct sockaddr*)&clientaddr, &clilen, 0);
    88. set_recv_event(&ring, connfd, buffer, 1024, 0);
    89. } else if (ci.event == EVENT_READ) {
    90. if (cqe->res < 0) continue;
    91. if (cqe->res == 0) {
    92. close(ci.connfd);
    93. } else {
    94. printf("recv --> %s, %d\n", buffer, cqe->res);
    95. //set_recv_event(&ring, ci.connfd, buffer, 1024, 0);
    96. set_send_event(&ring, ci.connfd, buffer, cqe->res, 0);
    97. }
    98. } else if (ci.event == EVENT_WRITE) { //
    99. //printf("write complete\n");
    100. set_recv_event(&ring, ci.connfd, buffer, 1024, 0);
    101. }
    102. }
    103. io_uring_cq_advance(&ring, cqecount);
    104. }
    105. getchar();
    106. }

    编译程序

    gcc -o ioring ioring.cpp -luring -static
    

    之后程序起来之后 用网络调试助手 发送测试文字

    先做个记录

  • 相关阅读:
    在Maya中想要使用Arnold渲染出高质量作品,这些技巧很重要
    web:[HCTF 2018]WarmUp
    vue3中使用setup语法糖使用
    LVGL V8.2字符串显示在Keil MDK上需要注意的事项(以小熊派为例)
    UDP网络编程
    网络安全系列-三十四: EDR、NDR、XDR 、HIPS、NIPS、NTA、DPI、DFI、南北流量、东西流量:傻傻分不清楚
    JavaScript扫盲及DOM的特点
    【SVM分类】基于matlab粒子群算法优化SVM分类【含Matlab源码 1859期】
    cmd命令行,杀掉某个进程,以(Anaconda为例)
    初始环境配置
  • 原文地址:https://blog.csdn.net/baoecit/article/details/133091216