当前位置: 首页 > news >正文

io_uring异步IO

io_uring介绍

io_uring是一个Linux内核的异步I/O框架,它提供了高性能的异步I/O操作,io_uring的目标是通过减少系统调用和上下文切换的开销来提高I/O操作的性能。

在网络编程中,我们通常使用epoll IO多路复用来处理网络IO,然而epoll也并不是异步网络IO,仅仅是内核提供了IO复用机制,epoll回调通知的是数据可以读取或者写入了,具体的读写操作仍然需要用户去做,而不是内核代替完成。

io_uring原理介绍:

kernel_new_features/io_uring/文章/浅析开源项目之io_uring.md at main · 0voice/kernel_new_features · GitHubi

io_uring实现tcp服务器

安装liburing

git clone https://github.com/axboe/liburing.git

./configure

make

make install

代码

#include <stdio.h>
#include <liburing.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>#define EVENT_ACCEPT   	0
#define EVENT_READ		1
#define EVENT_WRITE		2#define ENTRIES_LENGTH		1024
#define BUFFER_LENGTH		1024struct conn_info {int fd;int event;char buf[BUFFER_LENGTH];
};int init_server(unsigned short port) {	int sockfd = socket(AF_INET, SOCK_STREAM, 0);	struct sockaddr_in serveraddr;	memset(&serveraddr, 0, sizeof(struct sockaddr_in));	serveraddr.sin_family = AF_INET;	serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);	serveraddr.sin_port = htons(port);	if (-1 == bind(sockfd, (struct sockaddr*)&serveraddr, sizeof(struct sockaddr))) {		perror("bind");		return -1;	}	listen(sockfd, 10);return sockfd;
}int set_event_recv(struct io_uring *ring,struct conn_info *info, int flags) {struct io_uring_sqe *sqe = io_uring_get_sqe(ring);info->event = EVENT_READ;io_uring_prep_recv(sqe, info->fd, info->buf, BUFFER_LENGTH, flags);io_uring_sqe_set_data(sqe, info);
}int set_event_send(struct io_uring *ring,struct conn_info *info, size_t len, int flags) {struct io_uring_sqe *sqe = io_uring_get_sqe(ring);info->event = EVENT_WRITE;io_uring_prep_send(sqe, info->fd, info->buf, len, flags);io_uring_sqe_set_data(sqe, info);
}int set_event_accept(struct io_uring *ring, struct conn_info *info, struct sockaddr *addr, socklen_t *addrlen, int flags) {struct io_uring_sqe *sqe = io_uring_get_sqe(ring);info->event = EVENT_ACCEPT;io_uring_prep_accept(sqe, info->fd, (struct sockaddr*)addr, addrlen, flags);io_uring_sqe_set_data(sqe, info);
}int main(int argc, char *argv[]) {unsigned short port = 9999;int sockfd = init_server(port);struct io_uring_params params;memset(&params, 0, sizeof(params));struct io_uring ring;io_uring_queue_init_params(ENTRIES_LENGTH, &ring, &params);struct sockaddr_in clientaddr;	socklen_t len = sizeof(clientaddr);struct conn_info *accept_info = malloc(sizeof(struct conn_info));memset(accept_info, 0, sizeof(struct conn_info));accept_info->fd = sockfd;accept_info->event = EVENT_ACCEPT;set_event_accept(&ring, accept_info, (struct sockaddr*)&clientaddr, &len, 0);while (1) {io_uring_submit(&ring);struct io_uring_cqe *cqe;io_uring_wait_cqe(&ring, &cqe);struct io_uring_cqe *cqes[128];int nready = io_uring_peek_batch_cqe(&ring, cqes, 128);  // epoll_waitint i = 0;for (i = 0;i < nready;i ++) {struct io_uring_cqe *entries = cqes[i];struct conn_info *result = io_uring_cqe_get_data(entries);if (result->event == EVENT_ACCEPT) {set_event_accept(&ring, result, (struct sockaddr*)&clientaddr, &len, 0);//printf("set_event_accept\n"); //int connfd = entries->res;struct conn_info *info = malloc(sizeof(struct conn_info));memset(info, 0, sizeof(struct conn_info));info->fd = connfd;set_event_recv(&ring, info, 0);} else if (result->event == EVENT_READ) {  //int ret = entries->res;//printf("set_event_recv ret: %d, %s\n", ret, result->buf); //if (ret == 0) {close(result->fd);} else if (ret > 0) {set_event_send(&ring, result, ret, 0);}}  else if (result->event == EVENT_WRITE) {//int ret = entries->res;//printf("set_event_send ret: %d, %s\n", ret, result->buf);set_event_recv(&ring, result, 0);}}io_uring_cq_advance(&ring, nready);}}

运行环境内核版本:Linux version 5.15.0-119-generic,尽量高点,不然容易报错

测试:客户端建立50个连接,发送1百万个请求,测试QPS

收发包框架\数据包大小641282565121024
io_uring8401282345803088262481752
epoll7414573561738667494072358

 io_uring qps比epoll块10%左右

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • TDengine 与飞腾腾锐 D2000 完成兼容互认证,推动国产软硬件深度融合
  • Azkaban、oozie、airflow、dolphinschduler 对比分析
  • Jupyter Notebook远程登录配置
  • 前端用html写excel文件直接打开
  • 二维码扫码模组国产麒麟系统C语言SDK二次开发
  • 【PostgreSQL数据库表膨胀的一些原因】
  • 系统架构师考试学习笔记第五篇——架构设计补充知识(26)论文写作
  • 响应式网站真的就只是多了一个媒体查询吗?
  • 数仓建设:为什么我们的数据容易被业务方质疑?
  • 关于codesys循环结束,循环内累加值仍不停止累加问题
  • 002集—— CAD划线并模拟向命令窗口发送命令(CAD—C#二次开发入门)
  • 绿荫德清,数聚聚宝汇智—聚宝用户夏日交流会圆满落幕
  • linux 操作系统下cu命令介绍和使用案例
  • PHP悦读随行一键借阅图书小程序
  • 计算机网络:概述 - 性能指标
  • EventListener原理
  • JavaScript-Array类型
  • JavaScript对象详解
  • Java教程_软件开发基础
  • Netty 框架总结「ChannelHandler 及 EventLoop」
  • Node项目之评分系统(二)- 数据库设计
  • npx命令介绍
  • Spring框架之我见(三)——IOC、AOP
  • Sublime Text 2/3 绑定Eclipse快捷键
  • 读懂package.json -- 依赖管理
  • 浮现式设计
  • 类orAPI - 收藏集 - 掘金
  • 爬虫模拟登陆 SegmentFault
  • 前嗅ForeSpider教程:创建模板
  • 格斗健身潮牌24KiCK获近千万Pre-A轮融资,用户留存高达9个月 ...
  • # Swust 12th acm 邀请赛# [ K ] 三角形判定 [题解]
  • #git 撤消对文件的更改
  • (1)Hilt的基本概念和使用
  • (3)nginx 配置(nginx.conf)
  • (ctrl.obj) : error LNK2038: 检测到“RuntimeLibrary”的不匹配项: 值“MDd_DynamicDebug”不匹配值“
  • (day 2)JavaScript学习笔记(基础之变量、常量和注释)
  • (html转换)StringEscapeUtils类的转义与反转义方法
  • (libusb) usb口自动刷新
  • (ros//EnvironmentVariables)ros环境变量
  • (分享)自己整理的一些简单awk实用语句
  • (十一)JAVA springboot ssm b2b2c多用户商城系统源码:服务网关Zuul高级篇
  • (续)使用Django搭建一个完整的项目(Centos7+Nginx)
  • (一)Kafka 安全之使用 SASL 进行身份验证 —— JAAS 配置、SASL 配置
  • (一)u-boot-nand.bin的下载
  • (一)utf8mb4_general_ci 和 utf8mb4_unicode_ci 适用排序和比较规则场景
  • (一)项目实践-利用Appdesigner制作目标跟踪仿真软件
  • (原創) 如何將struct塞進vector? (C/C++) (STL)
  • (转)nsfocus-绿盟科技笔试题目
  • (转)原始图像数据和PDF中的图像数据
  • (最新)华为 2024 届秋招-硬件技术工程师-单板硬件开发—机试题—(共12套)(每套四十题)
  • ******IT公司面试题汇总+优秀技术博客汇总
  • .equals()到底是什么意思?
  • .NET C# 使用 iText 生成PDF
  • .NET C# 使用 SetWindowsHookEx 监听鼠标或键盘消息以及此方法的坑
  • .Net Core 微服务之Consul(二)-集群搭建