kvstore--io_uring

news/2025/2/25 0:21:20/文章来源:https://www.cnblogs.com/nakjima/p/18735245

io_uring.c

  #include <stdio.h>
#include <liburing.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>// 定义事件类型
#define EVENT_ACCEPT    0  // 接受新连接事件
#define EVENT_READ      1  // 读事件
#define EVENT_WRITE     2  // 写事件// 外部声明的协议处理函数
extern int kvs_protocol(char *msg, int length, char *response);// 定义连接信息结构体
struct conn_info {int fd;     // 文件描述符int event;  // 事件类型
};// 初始化服务器并监听指定端口
int p_init_server(unsigned short port) {int sockfd = socket(AF_INET, SOCK_STREAM, 0);  // 创建TCP套接字if (sockfd < 0) {perror("socket creation failed");return -1;}struct sockaddr_in serveraddr;memset(&serveraddr, 0, sizeof(struct sockaddr_in));  // 初始化地址结构serveraddr.sin_family = AF_INET;  // IPv4serveraddr.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);  // 开始监听,最大连接队列长度为10return sockfd;  // 返回监听套接字
}// 定义常量
#define ENTRIES_LENGTH  1024  // io_uring队列的大小
#define BUFFER_LENGTH   1024  // 数据缓冲区大小// 设置接收事件
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);  // 获取一个SQE(提交队列条目)if (!sqe) {return -1;  // 如果队列已满,返回错误}struct conn_info accept_info = {.fd = sockfd,.event = EVENT_READ,};io_uring_prep_recv(sqe, sockfd, buf, len, flags);  // 准备接收操作memcpy(&sqe->user_data, &accept_info, sizeof(struct conn_info));  // 将连接信息存储到user_data中return 0;
}// 设置发送事件
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);  // 获取一个SQEif (!sqe) {return -1;  // 如果队列已满,返回错误}struct conn_info accept_info = {.fd = sockfd,.event = EVENT_WRITE,};io_uring_prep_send(sqe, sockfd, buf, len, flags);  // 准备发送操作memcpy(&sqe->user_data, &accept_info, sizeof(struct conn_info));  // 将连接信息存储到user_data中return 0;
}// 设置接受新连接事件
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);  // 获取一个SQEif (!sqe) {return -1;  // 如果队列已满,返回错误}struct conn_info accept_info = {.fd = sockfd,.event = EVENT_ACCEPT,};io_uring_prep_accept(sqe, sockfd, (struct sockaddr*)addr, addrlen, flags);  // 准备接受新连接操作memcpy(&sqe->user_data, &accept_info, sizeof(struct conn_info));  // 将连接信息存储到user_data中return 0;
}// 定义消息处理函数类型
typedef int (*msg_handler)(char *msg, int length, char *response);
static msg_handler kvs_handler;  // 全局消息处理函数指针// 启动Proactor模型的服务器
int proactor_start(unsigned short port, msg_handler handler) {int sockfd = p_init_server(port);  // 初始化服务器并监听端口if (sockfd < 0) {return -1;  // 初始化失败时返回错误}kvs_handler = handler;  // 设置消息处理函数// 初始化io_uring参数struct io_uring_params params;memset(&params, 0, sizeof(params));// 初始化io_uring实例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);// 定义数据缓冲区和响应缓冲区char buffer[BUFFER_LENGTH] = {0};char response[BUFFER_LENGTH] = {0};// 主循环while (1) {io_uring_submit(&ring);  // 提交SQE到内核// 等待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);  // 获取批量完成事件for (int i = 0; i < nready; i++) {struct io_uring_cqe *entries = cqes[i];  // 当前完成事件struct conn_info result;memcpy(&result, &entries->user_data, sizeof(struct conn_info));  // 提取连接信息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) {  // 成功读取数据// 调用消息处理函数ret = kvs_handler(buffer, ret, response);// 注册写事件set_event_send(&ring, result.fd, response, ret, 0);}} else if (result.event == EVENT_WRITE) {  // 处理写事件int ret = entries->res;  // 获取写入的字节数set_event_recv(&ring, result.fd, buffer, BUFFER_LENGTH, 0);  // 注册读事件}}io_uring_cq_advance(&ring, nready);  // 提交处理完成的CQE}
}

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

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

相关文章

「跟着渡一学前端」并发请求实现

学习资源 并发请求 【渡一教育】 完整代码 function concurRequest(urls, maxNum) {if (urls.length === 0) {return Promise.resolve([]);}return new Promise((resolve) => {let nextIndex = 0;let finishCount = 0;const result = [];async function _request() {if (nex…

软工作业1

作业相关信息这个作业属于哪个课程 软件工程 这个作业要求在哪里 自我介绍+软工5问 这个作业的目标 自我介绍,了解软件工程基本概念个人介绍 Im YiLaiL YiLaiL/YiLaiL is a ✨ special ✨ repository because its README.md (this file) appears on your GitHub profile.🔭 …

EmEdit设置缓存目录临时文件夹

前言全局说明一、说明 1.1 环境: Windows 11 家庭版 23H2 22631.3737 EmEditor Professional (64-bit) Version 17.2.4二、打开大文本控制器三、点击右边大文本控制器上 自定义四、选择比较大的磁盘空间作为缓存空间免责声明:本号所涉及内容仅供安全研究与教学使用,如出现其他…

谈谈 ES 6.8 到 7.10 的功能变迁(3)- 查询方法篇

上一篇咱们了解了 ES 7.10 相较于 ES 6.8 新增的字段类型,这一篇我们继续了解新增的查询方法。 Interval 间隔查询: 功能介绍 Interval 查询,词项间距查询,可以根据匹配词项的顺序、间距和接近度对文档进行排名。主要解决的查询场景“创建一个多搜索词匹配的查询,同时保留…

【蓝牙小程序】在微信小程序中使用 ECharts

echarts-for-weixin 项目提供了一个小程序组件,用这种方式可以方便地使用 ECharts。 使用方式下载该项目 如有必要,将 ec-canvas 目录下的 echarts.js 替换为最新版的 ECharts。如果希望减小包体积大小,可以使用自定义构建生成并替换 echarts.js pages 目录下是使用的示例文…

Virtual Box设置双网卡

一、硬件 1.为虚拟机添加网卡2.配置网卡二、软件 3.获取mac地址 命令:ip link [root@vbox network-scripts]# ip link 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000link/loopback 00:00:00:00:00:00 brd…

简单逆向Java程序

前置 来源 这个程序是我同学编写的一个学生分数管理系统,我将对这个已经编译的程序进行测试、逆向,找出其中的问题,并进行改进。 运行环境macOS 15.4 IntelliJ IDEA 2024.2.3 OpenJDK 23.0.2 TomCat 11.0.4 Safari 15.4运行结果主要问题 在使用了这个程序之后,我发现了以下…

信息论概述

1 信息与消息 1.1 信息 1.1.1 信息的定义 信息是信息论中最基本、最重要的概念 香农信息的定义:信息是事物运动状态或存在方式的不确定描述 1.1.2 (香农)信息的度量样本空间:对于我们需要描述的事物中,事物可能存在不同的状态,即事物展现出来的多种状态。那么为了便于形容事…

JUC并发—12.ThreadLocal源码分析

大纲 1.ThreadLocal的特点介绍 2.ThreadLocal的使用案例 3.ThreadLocal的内部结构 4.ThreadLocal的核心方法源码 5.ThreadLocalMap的核心方法源码 6.ThreadLocalMap的原理总结1.ThreadLocal的特点介绍 (1)ThreadLocal的注释说明 (2)ThreadLocal的常用方法 (3)ThreadLocal的使用…

前端Vue创建

一、创建Vue项目二、导入idea 复制景区 三、设置main.js点击查看代码 import Vue from vue import App from ./App.vue import ElementUI from element-ui; import element-ui/lib/theme-chalk/index.css; import ./assets/golbal.css; import axios from axios; // 正确的模块…

朋友说喊搞个简单的微信对接的封装搞外包,不要那么多的方法拿来就用的的那种,来看看Simple.Wechat吧

朋友说喊搞个简单的微信对接的封装搞外包,不要那么多的方法拿来就用的的那种,来看看Simple.Wechat吧😂不知道大家有没有和我朋友一样,很多时候做外包总免不了去对接微信,最简单的微信用户信息获取、微信支付、微信模板消息发送,要是不熟悉总是要去找这个那个的包,但是人…