iouring系统调用及示例
io_uring 系统调用详解
1. 函数介绍
io_uring 是Linux 5.1引入的高性能异步I/O框架,提供了一种现代化的异步I/O接口。相比传统的AIO(异步I/O),io_uring具有更好的性能、更低的系统调用开销和更丰富的功能。它使用共享内存环形缓冲区实现用户空间和内核空间的高效通信。
2. 函数原型
#include <liburing.h>
#include <linux/io_uring.h>// 初始化io_uring实例
int io_uring_queue_init(unsigned entries, struct io_uring *ring, unsigned flags);// 销毁io_uring实例
int io_uring_queue_exit(struct io_uring *ring);// 提交I/O请求
int io_uring_submit(struct io_uring *ring);// 等待I/O完成事件
int io_uring_wait_cqe(struct io_uring *ring, struct io_uring_cqe **cqe_ptr);// 标记完成事件已处理
void io_uring_cqe_seen(struct io_uring *ring, struct io_uring_cqe *cqe);// 准备I/O操作
void io_uring_prep_read(struct io_uring_sqe *sqe, int fd, void *buf, unsigned nbytes, __u64 offset);
void io_uring_prep_write(struct io_uring_sqe *sqe, int fd, const void *buf, unsigned nbytes, __u64 offset);
void io_uring_prep_openat(struct io_uring_sqe *sqe, int dfd, const char *path, int flags, mode_t mode);
void io_uring_prep_close(struct io_uring_sqe *sqe, int fd);
void io_uring_prep_fsync(struct io_uring_sqe *sqe, int fd, unsigned fsync_flags);
3. 功能
io_uring 提供了完整的异步I/O解决方案,支持文件I/O、网络I/O、文件操作等多种操作类型。它通过共享内存环形缓冲区实现零拷贝的数据传输,显著提高了I/O性能。
4. 参数说明
io_uring_queue_init参数:
- unsigned entries: 环形缓冲区大小(必须是2的幂)
- *struct io_uring ring: io_uring实例指针
- unsigned flags: 初始化标志
io_uring_queue_exit参数:
- *struct io_uring ring: 要销毁的io_uring实例
io_uring_submit参数:
- *struct io_uring ring: io_uring实例
io_uring_wait_cqe参数:
- *struct io_uring ring: io_uring实例
- **struct io_uring_cqe cqe_ptr: 完成事件指针
5. 返回值
- 成功: 返回非负值或0
- 失败: 返回负的错误码
6. 相似函数,或关联函数
- io_setup/io_destroy: 传统的AIO接口
- io_submit/io_cancel: 传统的AIO提交和取消
- io_getevents: 传统的AIO事件获取
- aio_read/aio_write: POSIX AIO接口
- epoll_wait/poll: 传统的I/O多路复用
7. 示例代码
示例1:基础io_uring使用
#include <liburing.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>/*** 演示基础io_uring使用方法*/
int demo_io_uring_basic() {struct io_uring ring;int ret;printf("=== 基础io_uring使用示例 ===\n");// 初始化io_uring实例printf("1. 初始化io_uring实例:\n");ret = io_uring_queue_init(32, &ring, 0);if (ret < 0) {printf(" 初始化失败: %s\n", strerror(-ret));return -1;}printf(" ✓ io_uring实例初始化成功\n");printf(" 环形缓冲区大小: 32\n");// 显示io_uring信息printf(" io_uring信息:\n");printf(" 提交队列大小: %u\n", ring.sq.ring_sz);printf(" 完成队列大小: %u\n", ring.cq.ring_sz);printf(" 特性标志: 0x%x\n", ring.features);// 创建测试文件printf("\n2. 创建测试文件:\n");const char *test_filename = "io_uring_test.txt";int test_fd = open(test_filename, O_CREAT | O_WRONLY | O_TRUNC, 0644);if (test_fd == -1) {perror(" 创建测试文件失败");io_uring_queue_exit(&ring);return -1;}printf(" ✓ 测试文件创建成功: %s\n", test_filename);// 准备测试数据const char *test_data = "Hello from io_uring! This is a test message.\n";size_t data_size = strlen(test_data);// 使用io_uring写入数据printf("\n3. 使用io_uring写入数据:\n");struct io_uring_sqe *sqe = io_uring_get_sqe(&ring);if (!sqe) {printf(" 获取SQE失败\n");close(test_fd);unlink(test_filename);io_uring_queue_exit(&ring);return -1;}// 准备写入操作io_uring_prep_write(sqe, test_fd, test_data, data_size, 0);sqe->user_data = 1; // 设置用户数据printf(" 准备写入操作:\n");printf(" 文件描述符: %d\n", test_fd);printf(" 数据大小: %zu 字节\n", data_size);printf(" 偏移量: 0\n");// 提交操作ret = io_uring_submit(&ring);if (ret <= 0) {printf(" 提交操作失败: %s\n", strerror(-ret));close(test_fd);unlink(test_filename);io_uring_queue_exit(&ring);return -1;}printf(" ✓ 操作提交成功,提交了 %d 个请求\n", ret);// 等待完成printf("\n4. 等待I/O操作完成:\n");struct io_uring_cqe *cqe;ret = io_uring_wait_cqe(&ring, &cqe);if (ret < 0) {printf(" 等待完成事件失败: %s\n", strerror(-ret));close(test_fd);unlink(test_filename);io_uring_queue_exit(&ring);return -1;}printf(" ✓ I/O操作完成\n");printf(" 用户数据: %llu\n", (unsigned long long)cqe->user_data);printf(" 结果: %d 字节\n", cqe->res);printf(" 标志: 0x%x\n", cqe->flags);// 标记完成事件已处理io_uring_cqe_seen(&ring, cqe);// 读取写入的数据验证printf("\n5. 验证写入结果:\n");close(test_fd);test_fd = open(test_filename, O_RDONLY);if (test_fd != -1) {char read_buffer[256];ssize_t bytes_read = read(test_fd, read_buffer, sizeof(read_buffer) - 1);if (bytes_read > 0) {read_buffer[bytes_read] = '\0';printf(" 读取到的数据 (%zd 字节):\n", bytes_read);printf(" %s", read_buffer);}close(test_fd);}// 清理资源printf("\n6. 清理资源:\n");unlink(test_filename);io_uring_queue_exit(&ring);printf(" ✓ 资源清理完成\n");return 0;
}int main() {return demo_io_uring_basic();
}
示例2:批量I/O操作
#include <liburing.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h>/*** 批量I/O操作演示*/
int demo_batch_io_operations() {struct io_uring ring;const int batch_size = 8;const int file_count = 5;int ret;printf("=== 批量I/O操作演示 ===\n");// 初始化io_uringprintf("1. 初始化io_uring:\n");ret = io_uring_queue_init(64, &ring, 0);if (ret < 0) {printf(" 初始化失败: %s\n", strerror(-ret));return -1;}printf(" ✓ io_uring初始化成功\n");// 创建测试文件printf("\n2. 创建测试文件:\n");int file_fds[file_count];char filenames[file_count][32];for (int i = 0; i < file_count; i++) {snprintf(filenames[i], sizeof(filenames[i]), "batch_test_%d.txt", i);file_fds[i] = open(filenames[i], O_CREAT | O_WRONLY | O_TRUNC, 0644);if (file_fds[i] == -1) {perror(" 创建文件失败");// 清理已创建的文件for (int j = 0; j < i; j++) {close(file_fds[j]);unlink(filenames[j]);}io_uring_queue_exit(&ring);return -1;}printf(" 创建文件 %d: %s\n", i, filenames[i]);}// 准备批量写入操作printf("\n3. 准备批量写入操作:\n");char *test_data[file_count];int submitted_ops = 0;for (int i = 0; i < file_count; i++) {// 分配测试数据test_data[i] = malloc(256);if (!test_data[i]) {perror(" 分配测试数据失败");// 清理资源for (int j = 0; j <= i; j++) {if (test_data[j]) free(test_data[j]);if (j < file_count) {close(file_fds[j]);unlink(filenames[j]);}}io_uring_queue_exit(&ring);return -1;}snprintf(test_data[i], 256, "Batch write test data for file %d. Operation count: %d\n", i, i + 1);// 准备多个写入操作for (int j = 0; j < batch_size && submitted_ops < 32; j++) {struct io_uring_sqe *sqe = io_uring_get_sqe(&ring);if (!sqe) {printf(" 获取SQE失败\n");break;}// 准备写入操作io_uring_prep_write(sqe, file_fds[i], test_data[i], strlen(test_data[i]), j * 256);sqe->user_data = (i * batch_size + j); // 唯一标识符submitted_ops++;}printf(" 为文件 %d 准备了 %d 个写入操作\n", i, batch_size);}printf("\n4. 批量提交I/O操作:\n");printf(" 总共准备了 %d 个I/O操作\n", submitted_ops);ret = io_uring_submit(&ring);if (ret <= 0) {printf(" 提交操作失败: %s\n", strerror(-ret));} else {printf(" ✓ 成功提交 %d 个I/O操作\n", ret);}// 等待所有操作完成printf("\n5. 等待所有操作完成:\n");int completed_ops = 0;while (completed_ops < submitted_ops) {struct io_uring_cqe *cqe;ret = io_uring_wait_cqe(&ring, &cqe);if (ret < 0) {printf(" 等待完成事件失败: %s\n", strerror(-ret));break;}completed_ops++;printf(" 操作 %d 完成: 写入 %d 字节\n", (int)cqe->user_data, cqe->res);// 标记完成事件已处理io_uring_cqe_seen(&ring, cqe);}printf(" 总共完成了 %d 个I/O操作\n", completed_ops);// 验证写入结果printf("\n6. 验证写入结果:\n");for (int i = 0; i < file_count; i++) {close(file_fds[i]);// 重新打开文件读取int read_fd = open(filenames[i], O_RDONLY);if (read_fd != -1) {struct stat st;if (fstat(read_fd, &st) == 0) {printf(" 文件 %s: 大小 %ld 字节\n", filenames[i], st.st_size);}close(read_fd);}}// 清理资源printf("\n7. 清理资源:\n");for (int i = 0; i < file_count; i++) {free(test_data[i]);unlink(filenames[i]);}io_uring_queue_exit(&ring);printf(" ✓ 所有资源清理完成\n");return 0;
}int main() {return demo_batch_io_operations();
}
示例3:文件操作演示
#include <liburing.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h>/*** 文件操作结构*/
typedef struct {int fd;char filename[64];off_t file_size;int operation_type; // 0:read, 1:write, 2:open, 3:close, 4:fsync
} file_operation_t;/*** 演示文件操作*/
int demo_file_operations() {struct io_uring ring;int ret;printf("=== 文件操作演示 ===\n");// 初始化io_uringprintf("1. 初始化io_uring:\n");ret = io_uring_queue_init(16, &ring, 0);if (ret < 0) {printf(" 初始化失败: %s\n", strerror(-ret));return -1;}printf(" ✓ io_uring初始化成功\n");// 演示异步文件打开printf("\n2. 异步文件打开操作:\n");const char *test_filename = "async_file_test.txt";struct io_uring_sqe *sqe = io_uring_get_sqe(&ring);if (!sqe) {printf(" 获取SQE失败\n");io_uring_queue_exit(&ring);return -1;}// 准备打开文件操作io_uring_prep_openat(sqe, AT_FDCWD, test_filename, O_CREAT | O_RDWR | O_TRUNC, 0644);sqe->user_data = 1;printf(" 准备打开文件: %s\n", test_filename);ret = io_uring_submit(&ring);if (ret <= 0) {printf(" 提交打开操作失败: %s\n", strerror(-ret));io_uring_queue_exit(&ring);return -1;}// 等待打开完成struct io_uring_cqe *cqe;ret = io_uring_wait_cqe(&ring, &cqe);if (ret < 0) {printf(" 等待打开完成失败: %s\n", strerror(-ret));io_uring_queue_exit(&ring);return -1;}int file_fd = cqe->res;printf(" ✓ 文件打开成功,文件描述符: %d\n", file_fd);io_uring_cqe_seen(&ring, cqe);// 演示异步写入操作printf("\n3. 异步写入操作:\n");const char *write_data = "This is asynchronous write test data.\nMultiple lines of test content.\nEnd of test data.\n";size_t write_size = strlen(write_data);sqe = io_uring_get_sqe(&ring);if (!sqe) {printf(" 获取SQE失败\n");close(file_fd);unlink(test_filename);io_uring_queue_exit(&ring);return -1;}io_uring_prep_write(sqe, file_fd, write_data, write_size, 0);sqe->user_data = 2;printf(" 准备写入数据: %zu 字节\n", write_size);ret = io_uring_submit(&ring);if (ret <= 0) {printf(" 提交写入操作失败: %s\n", strerror(-ret));} else {printf(" ✓ 写入操作提交成功\n");}// 等待写入完成ret = io_uring_wait_cqe(&ring, &cqe);if (ret < 0) {printf(" 等待写入完成失败: %s\n", strerror(-ret));} else {printf(" ✓ 写入完成: %d 字节\n", cqe->res);io_uring_cqe_seen(&ring, cqe);}// 演示异步fsync操作printf("\n4. 异步fsync操作:\n");sqe = io_uring_get_sqe(&ring);if (sqe) {io_uring_prep_fsync(sqe, file_fd, 0);sqe->user_data = 3;printf(" 准备fsync操作\n");ret = io_uring_submit(&ring);if (ret > 0) {ret = io_uring_wait_cqe(&ring, &cqe);if (ret == 0) {printf(" ✓ fsync完成\n");io_uring_cqe_seen(&ring, cqe);}}}// 演示异步读取操作printf("\n5. 异步读取操作:\n");char read_buffer[256];sqe = io_uring_get_sqe(&ring);if (sqe) {io_uring_prep_read(sqe, file_fd, read_buffer, sizeof(read_buffer) - 1, 0);sqe->user_data = 4;printf(" 准备读取操作\n");ret = io_uring_submit(&ring);if (ret > 0) {ret = io_uring_wait_cqe(&ring, &cqe);if (ret == 0) {if (cqe->res > 0) {read_buffer[cqe->res] = '\0';printf(" ✓ 读取完成: %d 字节\n", cqe->res);printf(" 读取内容:\n%s", read_buffer);} else {printf(" 读取失败或文件为空\n");}io_uring_cqe_seen(&ring, cqe);}}}// 演示异步关闭操作printf("\n6. 异步关闭操作:\n");sqe = io_uring_get_sqe(&ring);if (sqe) {io_uring_prep_close(sqe, file_fd);sqe->user_data = 5;printf(" 准备关闭文件\n");ret = io_uring_submit(&ring);if (ret > 0) {ret = io_uring_wait_cqe(&ring, &cqe);if (ret == 0) {printf(" ✓ 文件关闭完成\n");io_uring_cqe_seen(&ring, cqe);}}}// 清理资源printf("\n7. 清理资源:\n");unlink(test_filename);io_uring_queue_exit(&ring);printf(" ✓ 资源清理完成\n");return 0;
}int main() {return demo_file_operations();
}
示例4:网络I/O演示
#include <liburing.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>/*** 演示网络I/O操作*/
int demo_network_io() {struct io_uring ring;int ret;printf("=== 网络I/O操作演示 ===\n");// 初始化io_uringprintf("1. 初始化io_uring:\n");ret = io_uring_queue_init(32, &ring, 0);if (ret < 0) {printf(" 初始化失败: %s\n", strerror(-ret));return -1;}printf(" ✓ io_uring初始化成功\n");// 演示异步socket创建printf("\n2. 异步socket创建:\n");struct io_uring_sqe *sqe = io_uring_get_sqe(&ring);if (!sqe) {printf(" 获取SQE失败\n");io_uring_queue_exit(&ring);return -1;}// 注意:io_uring的网络I/O支持需要较新的内核版本printf(" 注意:网络I/O操作需要Linux 5.5+内核支持\n");printf(" 在本演示中,我们将展示准备网络操作的方法\n");// 演示网络操作准备(伪代码)printf("\n3. 网络操作准备示例:\n");printf(" // 创建TCP socket\n");printf(" sqe = io_uring_get_sqe(&ring);\n");printf(" io_uring_prep_socket(sqe, AF_INET, SOCK_STREAM, 0, 0);\n");printf(" sqe->user_data = 1;\n");printf("\n");printf(" // 连接服务器\n");printf(" struct sockaddr_in addr;\n");printf(" memset(&addr, 0, sizeof(addr));\n");printf(" addr.sin_family = AF_INET;\n");printf(" addr.sin_port = htons(80);\n");printf(" addr.sin_addr.s_addr = inet_addr(\"127.0.0.1\");\n");printf(" io_uring_prep_connect(sqe, sockfd, &addr, sizeof(addr));\n");printf("\n");printf(" // 发送数据\n");printf(" const char *data = \"GET / HTTP/1.1\\r\\n\\r\\n\";\n");printf(" io_uring_prep_send(sqe, sockfd, data, strlen(data), 0);\n");printf("\n");printf(" // 接收数据\n");printf(" char buffer[1024];\n");printf(" io_uring_prep_recv(sqe, sockfd, buffer, sizeof(buffer), 0);\n");// 显示网络I/O优势printf("\n=== 网络I/O优势 ===\n");printf("1. 高性能:\n");printf(" ✓ 零拷贝数据传输\n");printf(" ✓ 减少系统调用开销\n");printf(" ✓ 提高并发处理能力\n");printf("\n2. 低延迟:\n");printf(" ✓ 快速事件通知\n");printf(" ✓ 减少上下文切换\n");printf(" ✓ 优化内存访问模式\n");printf("\n3. 可扩展性:\n");printf(" ✓ 支持大量并发连接\n");printf(" ✓ 高效的事件处理\n");printf(" ✓ 灵活的缓冲区管理\n");// 清理资源printf("\n4. 清理资源:\n");io_uring_queue_exit(&ring);printf(" ✓ io_uring资源清理完成\n");return 0;
}int main() {return demo_network_io();
}
示例5:性能对比测试
#include <liburing.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <sys/time.h>
#include <time.h>/*** 性能测试结果结构*/
typedef struct {const char *test_name;long long execution_time_us;int operation_count;double throughput_ops;double average_latency_us;
} performance_result_t;/*** 获取当前时间(微秒)*/
long long get_current_time_us() {struct timeval tv;gettimeofday(&tv, NULL);return tv.tv_sec * 1000000LL + tv.tv_usec;
}/*** 传统同步I/O性能测试*/
int test_sync_io_performance(performance_result_t *result) {const int operation_count = 1000;const size_t buffer_size = 4096;char *buffer = malloc(buffer_size);long long start_time, end_time;if (!buffer) {return -1;}printf("执行同步I/O性能测试...\n");// 创建测试文件const char *filename = "sync_test.dat";int fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0644);if (fd == -1) {free(buffer);return -1;}start_time = get_current_time_us();// 执行同步写入操作for (int i = 0; i < operation_count; i++) {// 填充测试数据for (size_t j = 0; j < buffer_size; j++) {buffer[j] = 'A' + (i + j) % 26;}ssize_t written = write(fd, buffer, buffer_size);if (written != (ssize_t)buffer_size) {printf("写入失败\n");close(fd);unlink(filename);free(buffer);return -1;}}end_time = get_current_time_us();close(fd);unlink(filename);free(buffer);result->execution_time_us = end_time - start_time;result->operation_count = operation_count;result->throughput_ops = (double)operation_count / (result->execution_time_us / 1000000.0);result->average_latency_us = (double)result->execution_time_us / operation_count;printf("同步I/O测试完成\n");return 0;
}/*** io_uring异步I/O性能测试*/
int test_io_uring_performance(performance_result_t *result) {struct io_uring ring;const int operation_count = 1000;const size_t buffer_size = 4096;char **buffers;long long start_time, end_time;int ret;printf("执行io_uring异步I/O性能测试...\n");// 初始化io_uringret = io_uring_queue_init(256, &ring, 0);if (ret < 0) {printf("io_uring初始化失败: %s\n", strerror(-ret));return -1;}// 分配缓冲区buffers = malloc(operation_count * sizeof(char*));if (!buffers) {io_uring_queue_exit(&ring);return -1;}for (int i = 0; i < operation_count; i++) {buffers[i] = malloc(buffer_size);if (!buffers[i]) {// 清理已分配的缓冲区for (int j = 0; j < i; j++) {free(buffers[j]);}free(buffers);io_uring_queue_exit(&ring);return -1;}// 填充测试数据for (size_t j = 0; j < buffer_size; j++) {buffers[i][j] = 'A' + (i + j) % 26;}}// 创建测试文件const char *filename = "async_test.dat";int fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0644);if (fd == -1) {perror("创建测试文件失败");// 清理缓冲区for (int i = 0; i < operation_count; i++) {free(buffers[i]);}free(buffers);io_uring_queue_exit(&ring);return -1;}start_time = get_current_time_us();// 提交异步写入操作int submitted = 0;for (int i = 0; i < operation_count; i++) {struct io_uring_sqe *sqe = io_uring_get_sqe(&ring);if (!sqe) {printf("获取SQE失败\n");break;}io_uring_prep_write(sqe, fd, buffers[i], buffer_size, i * buffer_size);sqe->user_data = i;submitted++;// 定期提交操作if (submitted % 32 == 0 || i == operation_count - 1) {ret = io_uring_submit(&ring);if (ret < 0) {printf("提交操作失败: %s\n", strerror(-ret));break;}}}printf("提交了 %d 个异步操作\n", submitted);// 等待所有操作完成int completed = 0;while (completed < submitted) {struct io_uring_cqe *cqe;ret = io_uring_wait_cqe(&ring, &cqe);if (ret < 0) {printf("等待完成事件失败: %s\n", strerror(-ret));break;}completed++;io_uring_cqe_seen(&ring, cqe);}end_time = get_current_time_us();printf("完成了 %d 个异步操作\n", completed);// 清理资源close(fd);unlink(filename);for (int i = 0; i < operation_count; i++) {free(buffers[i]);}free(buffers);io_uring_queue_exit(&ring);result->execution_time_us = end_time - start_time;result->operation_count = completed;result->throughput_ops = (double)completed / (result->execution_time_us / 1000000.0);result->average_latency_us = (double)result->execution_time_us / completed;printf("io_uring异步I/O测试完成\n");return 0;
}/*** 演示性能对比测试*/
int demo_performance_comparison() {performance_result_t sync_result = {0};performance_result_t async_result = {0};printf("=== io_uring vs 同步I/O 性能对比 ===\n");// 设置测试结果名称sync_result.test_name = "同步I/O";async_result.test_name = "io_uring异步I/O";// 执行同步I/O测试printf("1. 执行同步I/O测试:\n");if (test_sync_io_performance(&sync_result) != 0) {printf(" 同步I/O测试失败\n");return -1;}printf(" 测试完成\n");// 执行io_uring测试printf("\n2. 执行io_uring异步I/O测试:\n");if (test_io_uring_performance(&async_result) != 0) {printf(" io_uring测试失败\n");return -1;}printf(" 测试完成\n");// 显示测试结果printf("\n=== 性能测试结果 ===\n");printf("%-20s %-15s %-15s %-15s %-15s\n","测试类型", "操作次数", "耗时(μs)", "吞吐量(ops/s)", "平均延迟(μs)");printf("%-20s %-15s %-15s %-15s %-15s\n","--------", "--------", "--------", "------------", "------------");printf("%-20s %-15d %-15lld %-15.0f %-15.2f\n",sync_result.test_name,sync_result.operation_count,sync_result.execution_time_us,sync_result.throughput_ops,sync_result.average_latency_us);printf("%-20s %-15d %-15lld %-15.0f %-15.2f\n",async_result.test_name,async_result.operation_count,async_result.execution_time_us,async_result.throughput_ops,async_result.average_latency_us);// 性能对比分析printf("\n=== 性能对比分析 ===\n");if (sync_result.execution_time_us > 0 && async_result.execution_time_us > 0) {double time_improvement = (double)sync_result.execution_time_us / async_result.execution_time_us;double throughput_improvement = async_result.throughput_ops / sync_result.throughput_ops;double latency_reduction = (sync_result.average_latency_us - async_result.average_latency_us) / sync_result.average_latency_us * 100;printf("执行时间对比: %.2f 倍提升\n", time_improvement);printf("吞吐量对比: %.2f 倍提升\n", throughput_improvement);printf("平均延迟减少: %.1f%%\n", latency_reduction);}// 显示优势分析printf("\n=== 优势分析 ===\n");printf("1. io_uring优势:\n");printf(" ✓ 零拷贝数据传输\n");printf(" ✓ 减少系统调用次数\n");printf(" ✓ 提高I/O并发性能\n");printf(" ✓ 更好的CPU利用率\n");printf("\n2. 适用场景:\n");printf(" ✓ 高并发网络服务器\n");printf(" ✓ 大文件传输应用\n");printf(" ✓ 实时数据处理\n");printf(" ✓ 数据库存储引擎\n");printf("\n3. 性能优化建议:\n");printf(" ✓ 合理设置环形缓冲区大小\n");printf(" ✓ 批量提交I/O操作\n");printf(" ✓ 使用适当的等待策略\n");printf(" ✓ 监控系统资源使用\n");return 0;
}int main() {return demo_performance_comparison();
}
io_uring 使用注意事项
系统要求:
1. 内核版本: 需要Linux 5.1或更高版本
2. 架构支持: 支持所有主流架构
3. 编译要求: 需要liburing库支持
初始化选项:
- IORING_SETUP_IOPOLL: 启用I/O轮询模式
- IORING_SETUP_SQPOLL: 启用提交队列轮询
- IORING_SETUP_SQ_AFF: 设置提交队列CPU亲和性
- IORING_SETUP_CQSIZE: 设置完成队列大小
错误处理:
1. 负返回值: 表示错误码
2. errno设置: 传统错误码机制
3. 完成事件: 通过cqe->res返回结果
性能考虑:
1. 缓冲区大小: 合理设置环形缓冲区大小
2. 批量操作: 批量提交提高效率
3. 内存管理: 避免频繁的内存分配
4. CPU亲和性: 考虑CPU绑定优化
安全考虑:
1. 权限检查: 确保有足够的权限
2. 资源限制: 避免消耗过多系统资源
3. 输入验证: 验证所有输入参数
4. 错误恢复: 妥善处理各种错误情况
最佳实践:
- 环境检查: 使用前检查内核支持
- 参数验证: 验证所有输入参数
- 错误处理: 妥善处理各种错误
- 资源管理: 及时释放分配的资源
- 性能监控: 监控性能指标并优化
io_uring vs 传统AIO对比
传统AIO限制:
// 传统AIO接口
#include <linux/aio_abi.h>
int io_setup(unsigned nr_events, aio_context_t *ctxp);
int io_destroy(aio_context_t ctx);
int io_submit(aio_context_t ctx, long nr, struct iocb *ios[]);
int io_cancel(aio_context_t ctx, struct iocb *iocb, struct io_event *result);
int io_getevents(aio_context_t ctx, long min_nr, long nr, struct io_event *events, struct timespec *timeout);
io_uring优势:
// io_uring接口
#include <liburing.h>
int io_uring_queue_init(unsigned entries, struct io_uring *ring, unsigned flags);
int io_uring_queue_exit(struct io_uring *ring);
int io_uring_submit(struct io_uring *ring);
int io_uring_wait_cqe(struct io_uring *ring, struct io_uring_cqe **cqe_ptr);
性能对比数据
系统调用开销:
- 传统AIO: 每次操作需要多个系统调用
- io_uring: 批量操作减少系统调用次数
内存拷贝:
- 传统AIO: 需要多次内存拷贝
- io_uring: 零拷贝数据传输
并发性能:
- 传统AIO: 并发性能有限
- io_uring: 高并发性能优异
常见使用场景
1. 网络服务器:
// 高性能网络服务器
struct io_uring ring;
io_uring_queue_init(4096, &ring, 0);// 批量处理网络请求
for (int i = 0; i < connections; i++) {struct io_uring_sqe *sqe = io_uring_get_sqe(&ring);io_uring_prep_recv(sqe, conn_fd[i], buffer[i], buffer_size, 0);
}io_uring_submit(&ring);
2. 存储系统:
// 高性能存储系统
struct io_uring ring;
io_uring_queue_init(8192, &ring, IORING_SETUP_IOPOLL);// 批量存储操作
for (int i = 0; i < io_count; i++) {struct io_uring_sqe *sqe = io_uring_get_sqe(&ring);io_uring_prep_write(sqe, fd, data[i], size[i], offset[i]);
}io_uring_submit(&ring);
3. 数据库引擎:
// 数据库存储引擎
struct io_uring ring;
io_uring_queue_init(2048, &ring, 0);// 并发数据页读写
for (int i = 0; i < pages; i++) {struct io_uring_sqe *sqe = io_uring_get_sqe(&ring);io_uring_prep_read(sqe, fd, page_buffer[i], page_size, page_offset[i]);
}io_uring_submit(&ring);
总结
io_uring 是Linux系统中先进的异步I/O框架,提供了:
1. 高性能: 显著优于传统AIO的性能
2. 易用性: 简化的API设计
3. 灵活性: 丰富的操作类型支持
4. 可扩展性: 支持大规模并发操作
通过合理使用io_uring,可以构建高性能的I/O密集型应用。在实际应用中,需要注意内核版本要求、错误处理和性能优化等关键问题。