Linux io_uring

io_uring是Linux 内核提供的用于处理大量并发 I/O 事件的机制,在性能上优于epoll。

主要优势有:

(1)无锁设计:

io_uring:提供了无锁的用户空间和内核空间通信机制,这意味着在高并发场景下,io_uring 可以减少锁争用,提高性能。
(2)提交和完成队列:

io_uring:使用两个队列,一个是提交队列(submission queue),用于提交 I/O 请求;另一个是完成队列(completion queue),用于接收完成的 I/O 事件。这种分离可以减少内核和用户空间的交互次数。
epoll:使用一个事件列表来通知用户空间哪些 I/O 事件已经准备好。虽然 epoll 也提供了高效的 I/O 事件通知机制,但它通常需要更多的上下文切换和内核调用。
可扩展性:

(3)异步IO支持

io_uring:原生支持异步 I/O 操作,可以直接在用户空间管理 I/O 事件,减少了系统调用的开销。
epoll:主要用于通知 I/O 事件的就绪状态,但实际的 I/O 操作(如 read 和 write)仍然需要通过系统调用来完成。
 

下面实现一个简单的基于io_uring的TCP服务器

#include <stdio.h> // 包含标准输入输出库
#include <liburing.h> // 包含io_uring库,用于异步I/O操作
#include <netinet/in.h> // 包含网络接口的函数和常量
#include <string.h> // 包含字符串操作函数
#include <unistd.h> // 包含UNIX标准函数的定义#define EVENT_ACCEPT   	0 // 定义事件类型:接受连接
#define EVENT_READ		1 // 定义事件类型:读取数据
#define EVENT_WRITE		2 // 定义事件类型:写入数据struct conn_info { // 定义一个结构体用来存储连接信息int fd; // 文件描述符int event; // 事件类型
};// 初始化服务器并监听指定端口
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); // 服务器IP地址serveraddr.sin_port = htons(port); // 服务器端口// 绑定套接字到指定的地址和端口if (-1 == bind(sockfd, (struct sockaddr*)&serveraddr, sizeof(struct sockaddr))) {		perror("bind"); // 如果绑定失败,打印错误信息return -1; // 返回错误代码}	listen(sockfd, 10); // 开始监听套接字,最大连接数为10return sockfd; // 返回套接字描述符
}// 定义常量,设置io_uring的条目数量和缓冲区长度
#define ENTRIES_LENGTH		1024
#define BUFFER_LENGTH		1024// 设置接收事件
int set_event_recv(struct io_uring *ring, int sockfd,void *buf, size_t len, int flags) {// 获取一个SQE(提交队列条目)struct io_uring_sqe *sqe = io_uring_get_sqe(ring);// 准备接收数据的请求io_uring_prep_recv(sqe, sockfd, buf, len, flags);// 将conn_info结构体的值复制到SQE的用户数据区域memcpy(&sqe->user_data, &accept_info, sizeof(struct conn_info));
}// 设置发送事件
int set_event_send(struct io_uring *ring, int sockfd,void *buf, size_t len, int flags) {// 获取一个SQEstruct io_uring_sqe *sqe = io_uring_get_sqe(ring);// 准备发送数据的请求io_uring_prep_send(sqe, sockfd, buf, len, flags);// 复制conn_info到SQE的用户数据区域memcpy(&sqe->user_data, &accept_info, sizeof(struct conn_info));
}// 设置接受连接事件
int set_event_accept(struct io_uring *ring, int sockfd, struct sockaddr *addr,socklen_t *addrlen, int flags) {// 获取一个SQEstruct io_uring_sqe *sqe = io_uring_get_sqe(ring);// 准备接受连接的请求io_uring_prep_accept(sqe, sockfd, (struct sockaddr*)addr, addrlen, flags);// 复制conn_info到SQE的用户数据区域memcpy(&sqe->user_data, &accept_info, sizeof(struct conn_info));
}// 主函数
int main(int argc, char *argv[]) {// 设置服务器监听的端口unsigned short port = 9999;// 初始化服务器并获取套接字描述符int sockfd = init_server(port);// 初始化io_uring参数struct io_uring_params params;// 清零参数结构体memset(&params, 0, sizeof(params));// 初始化io_uringstruct io_uring ring;io_uring_queue_init_params(ENTRIES_LENGTH, &ring, &params);// 以下代码块被注释掉,说明原始代码可能考虑过使用传统的accept方法
#if 0// 省略的代码块
#else// 使用io_uring设置接受连接的事件set_event_accept(&ring, sockfd, (struct sockaddr*)&clientaddr, &len, 0);
#endif// 定义缓冲区用于数据交换char buffer[BUFFER_LENGTH] = {0};// 无限循环,处理io_uring事件while (1) {// 提交所有SQE到io_uringio_uring_submit(&ring);// 获取一个完成的CQE(完成队列条目)struct io_uring_cqe *cqe;io_uring_wait_cqe(&ring, &cqe);// 批量获取完成的CQEstruct io_uring_cqe *cqes[128];int nready = io_uring_peek_batch_cqe(&ring, cqes, 128);// 遍历所有完成的CQEint i = 0;for (i = 0; i < nready; i++) {// 获取CQEstruct io_uring_cqe *entries = cqes[i];// 创建conn_info结构体用于存储事件信息struct conn_info result;// 从CQE的用户数据区域复制conn_infomemcpy(&result, &entries->user_data, sizeof(struct conn_info));// 根据事件类型处理不同的I/O操作if (result.event == EVENT_ACCEPT) {// 处理接受连接事件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 ret = entries->res;if (ret == 0) {close(result.fd); // 如果读取结束,则关闭连接} else if (ret > 0) {set_event_send(&ring, result.fd, buffer, ret, 0); // 设置发送事件}} else if (result.event == EVENT_WRITE) {// 处理发送事件int ret = entries->res;set_event_recv(&ring, result.fd, buffer, BUFFER_LENGTH, 0); // 发送完成后设置读取事件}}// 推进CQ(完成队列)的偏移量io_uring_cq_advance(&ring, nready);}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/44333.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux C++ 047-设计模式之责任链模式

Linux C 047-设计模式之责任链模式 本节关键字&#xff1a;Linux、C、设计模式、责任链模式 相关库函数&#xff1a; 简介 责任链模式是面向对象中的一种软件设计模式&#xff0c;它包含了一些命令对象和一些处理对象&#xff0c;每个处理对象决定它能处理那些命令对象&…

C++中各类常用算法的总结以及使用

1.常用算法 文章目录 1.常用算法1.常用遍历算法1.for_each2.transform 2.常用查找算法1. find2. find_if3. adjacent_find4. binary_search5. count6. count_if 3.常用排序算法1. sort2. random_shuffle3. merge4. reverse 4.常用拷贝和替换算法1. copy2. replace3. replace_if…

如何在Vue中实现拖拽功能?

Vue.js是一款流行的JavaScript框架&#xff0c;用于构建用户界面。其中一个常见的需求是在Vue中实现拖拽功能&#xff0c;让用户可以通过拖拽元素来进行交互。今天&#xff0c;我们就来学习如何在Vue中实现这一功能。 首先&#xff0c;我们需要明白拖拽功能的基本原理&#xf…

一元非线性回归+多元线性回归

一元非线性回归 观察散点图&#xff0c;确定非线性形式&#xff0c;然后将非线性转化为线性求解。 常见的六类曲线&#xff1a; &#xff08;1&#xff09;双曲函数曲线 { y ^ x a b x y ^ a b x x y ^ 1 a b x \begin{cases} \hat{y}\frac{x}{abx}\\ \hat{y}\frac{abx…

【selenium】元素等待

【selenium】元素等待 1、三种元素等待的区别2、sleep等待3、隐式等待4、显示等待4.1 WebDriverWait类4.2 expected_conditions类 1、三种元素等待的区别 特点sleep隐式等待显示等待原理不论网页/元素是否加载完成&#xff0c;都会强制等待x秒设置一个等待时间&#xff0c;等待…

Java 修改微信公众号后台服务器地址URL后,微信公众平台客服功能接收不到用户发送的消息的解决办法

解决办法&#xff1a; 检查一下微信回调URL是否转发了客服消息。 /*** 处理具体的回调信息*/ PostMapping("/callback") public void callback(RequestParam(name "signature", required false) String signature,RequestParam(name "timestamp&q…

centos系统查找mysql的配置文件位置

执行命令查找mysql的安装目录&#xff1a; which mysql cd进入mysql的安装目录 cd /usr/bin 查找配置文件位置 ./mysql --help | grep "my.cnf" 定位配置文件 cd /etc 查找命令还可以用find命令 find / -name "my.cnf"

iOS UITableView自带滑动手势和父视图添加滑动手势冲突响应机制探索

场景 我们有时候会遇到这样的一个交互场景&#xff1a;我们有一个UITableView 放在一个弹窗中&#xff0c;这个弹窗可以通过滑动进行展示和消失&#xff08;跟手滑动的方式&#xff09;&#xff0c;然后这个UITableView放在弹窗中&#xff0c;并且可以滚动&#xff0c;展示一些…

用微信服务号支付门诊缴费

时间上午10刚过&#xff0c;医院里计价收费处排起了长龙&#xff0c;放眼望去&#xff0c;左边的窗口六条队。右边在原来发药的位置也开辟了收费窗口&#xff0c;数了一下有四条队。一共十条排队付费的长龙&#xff0c;每一条队伍的人数不下20人&#xff0c;也即超过200人在排队…

百度智能云将大模型引入网络故障定位的智能运维实践

物理网络中&#xff0c;某个设备发生故障&#xff0c;可能会引起一系列指标异常的告警。如何在短时间内从这些告警信息中找到真正的故障原因&#xff0c;犹如大海捞针&#xff0c;对于运维团队是一件很有挑战的事情。 在长期的物理网络运维工作建设中&#xff0c;百度智能云通…

【linux】linux的特殊符号

特殊字符用途示例,参数分隔符或命令分隔符git log --prettyformat:"%h,%an,%ar,%s"/文件路径分隔符&#xff0c;根目录cd /home/user/documents\转义字符&#xff0c;行继续echo "This is a long command \定义字符串&#xff0c;不解析变量和转义字符echo Hell…

探索 Postman API 网络图:可视化 API 交互的窗口

引言 在当今快速发展的软件开发领域&#xff0c;API&#xff08;应用程序编程接口&#xff09;扮演着至关重要的角色。Postman&#xff0c;作为业界领先的 API 开发工具&#xff0c;提供了一个强大的功能——API 网络图&#xff0c;它可以帮助开发者以图形化的方式理解和分析 …

【前端从入门到精通:第十一课: JS基本语法】

独闯JavaScript 了解JavaScript 为什么学习JavaScript JavaScript 是 web 开发者必学的三种语言之一&#xff1a; HTML 定义网页的内容 CSS 规定网页的布局 JavaScript 对网页行为进行编程 我们学习 JavaScript&#xff0c;以及 JavaScript 如何与 HTML 和 CSS 协同工作的知…

数字力量助西部职教全面提升——唯众品牌大数据、人工智能系列产品中标甘肃庆阳职院数字经济人才培养基地!

近日&#xff0c;唯众品牌凭借在大数据和人工智能领域深耕多年的技术积累和卓越产品&#xff0c;成功中标庆阳职业技术学院全国一体化算力网络国家枢纽节点数字经济人才培养基地项目&#xff0c;标志着唯众在助力西部职业教育与数字经济融合发展的新征程上迈出了坚实的一步。 …

Data Guard高级玩法:failover备库后,通过闪回恢复DG备库

作者介绍&#xff1a;老苏&#xff0c;10余年DBA工作运维经验&#xff0c;擅长Oracle、MySQL、PG、Mongodb数据库运维&#xff08;如安装迁移&#xff0c;性能优化、故障应急处理等&#xff09; 公众号&#xff1a;老苏畅谈运维 欢迎关注本人公众号&#xff0c;更多精彩与您分享…

怎样将aac转换mp3格式?推荐四个aac转MP3的方法

怎样将aac转换mp3格式&#xff1f;当需要将aac格式音频转换为MP3格式时&#xff0c;有几种方法可以轻松实现这一目标。MP3是一种广泛支持的音频格式&#xff0c;几乎所有设备和平台都能播放MP3文件&#xff0c;包括各种音乐播放器、手机、平板电脑和汽车音响系统。而且它也提供…

MySQL:视图、用户管理、C/C++/图形化界面链接访问数据库、网页逻辑

文章目录 1.视图1.1 视图的基本使用1.2 视图的基本规则 2.用户管理2.1 创建、删除、修改用户2.2 数据库权限 3.C/C/图形化界面链接访问数据库3.1 准备工作及常用接口介绍3.2 图形化界面访问MySQL 4.用户逻辑(注册&&登录) 1.视图 视图是一个虚拟表&#xff0c;其内容由…

嵌入式上gst rtsp server opencv mat

0 安装gstreamer sudo apt install libgstreamer1.0-0 gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-doc gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-…

请写sql满足业务:找到连续登录3天以上的用户

为了找到连续登录超过 3 天的用户&#xff0c;我们可以使用 SQL 窗口函数和递归查询来实现。假设有一个 user_logins 表&#xff0c;包含以下字段&#xff1a; user_id&#xff08;用户ID&#xff09;login_date&#xff08;登录日期&#xff09; 假设 login_date 是 DATE 类…

怎么提高音频声音大小?提高音频声音大小的四种方法

怎么提高音频声音大小&#xff1f;在音频处理和编辑中&#xff0c;增加声音的音量是一个常见的需求&#xff0c;尤其是在确保音频清晰度和听觉效果的同时。调整音频的音量不仅仅是简单地提高音频的响度&#xff0c;它也涉及到如何保持音质的高标准&#xff0c;确保没有失真或削…