当前位置: 首页 > 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%左右


http://www.mrgr.cn/news/23710.html

相关文章:

  • Python Web 框架篇:Flask、Django、FastAPI介绍及其核心技术
  • 关于2023.9.2~2023.9.10学习总结与教训
  • 【论软件需求获取方法及其应用】
  • 自定义类型:结构体
  • 多个微信是怎么进行管理的?
  • Notepad++ 修改 About
  • llvm使用
  • 蚂蚁数科,独行的170天和未来新征程
  • 第二百二十二节 JPA教程 - JPA合并示例
  • 所有企业都需要的6种市场营销代理报告
  • Visual studio 2022中配置c++版本的opencv
  • 乐观锁悲观锁
  • jina-embeddings 的使用教程,怎么用它做embeddings和rerank的操作呢?
  • 并发编程:AQS(下)
  • 2024年10款成名已久的企业防泄密软件,企业文件加密防泄密必备
  • python简单处理nmap的扫描结果
  • 报名啦|PolarDB数据库创新设计赛(天池杯)等你来战
  • 【C++11 ——— 可变参数模板】
  • Excel怎样计算梯度费用,就拿电费来举例计算
  • HarmonyOS开发之路由跳转