1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
| #define _GNU_SOURCE #include <sys/uio.h> #include <unistd.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h>
/** * 使用preadv进行分散读取 */ int demo_preadv_basic() { int fd; struct iovec iov[3]; char buf1[20], buf2[15], buf3[30]; ssize_t total_bytes; // 创建测试文件 fd = open("test_preadv.txt", O_CREAT | O_WRONLY | O_TRUNC, 0644); if (fd == -1) { perror("创建测试文件失败"); return -1; } // 写入测试数据 const char *test_data = "This is a long test string for preadv demonstration purposes."; write(fd, test_data, strlen(test_data)); close(fd); // 打开文件进行分散读取 fd = open("test_preadv.txt", O_RDONLY); if (fd == -1) { perror("打开文件失败"); return -1; } printf("=== preadv 基本使用示例 ===\n"); printf("测试数据: %s\n", test_data); printf("数据长度: %zu 字节\n\n", strlen(test_data)); // 设置iovec数组 iov[0].iov_base = buf1; iov[0].iov_len = sizeof(buf1) - 1; iov[1].iov_base = buf2; iov[1].iov_len = sizeof(buf2) - 1; iov[2].iov_base = buf3; iov[2].iov_len = sizeof(buf3) - 1; // 从偏移量0开始分散读取 total_bytes = preadv(fd, iov, 3, 0); if (total_bytes == -1) { perror("preadv 失败"); close(fd); return -1; } printf("preadv 读取了 %zd 字节到3个缓冲区:\n", total_bytes); // 添加字符串结束符并显示结果 buf1[iov[0].iov_len] = '\0'; buf2[iov[1].iov_len] = '\0'; buf3[iov[2].iov_len] = '\0'; printf("缓冲区1 (%zu字节): %s\n", iov[0].iov_len, buf1); printf("缓冲区2 (%zu字节): %s\n", iov[1].iov_len, buf2); printf("缓冲区3 (%zu字节): %s\n", iov[2].iov_len, buf3); close(fd); unlink("test_preadv.txt"); return 0; }
/** * 演示preadv读取结构体数据 */ struct Person { int id; char name[20]; float score; };
int demo_preadv_struct() { int fd; struct iovec iov[3]; struct Person person = {1001, "Alice Johnson", 95.5}; int read_id; char read_name[20]; float read_score; printf("\n=== preadv 读取结构体数据示例 ===\n"); // 创建包含结构体数据的文件 fd = open("person_data.bin", O_CREAT | O_WRONLY | O_TRUNC, 0644); if (fd == -1) { perror("创建数据文件失败"); return -1; } write(fd, &person, sizeof(person)); close(fd); // 使用preadv分别读取结构体的各个字段 fd = open("person_data.bin", O_RDONLY); if (fd == -1) { perror("打开数据文件失败"); return -1; } // 设置iovec读取结构体的各个部分 iov[0].iov_base = &read_id; iov[0].iov_len = sizeof(read_id); iov[1].iov_base = read_name; iov[1].iov_len = sizeof(read_name); iov[2].iov_base = &read_score; iov[2].iov_len = sizeof(read_score); ssize_t bytes_read = preadv(fd, iov, 3, 0); if (bytes_read == -1) { perror("preadv 读取结构体失败"); close(fd); return -1; } printf("读取了 %zd 字节的结构体数据:\n", bytes_read); printf("ID: %d\n", read_id); printf("Name: %s\n", read_name); printf("Score: %.1f\n", read_score); close(fd); unlink("person_data.bin"); return 0; }
int main() { if (demo_preadv_basic() == 0) { demo_preadv_struct(); printf("\n=== preadv 使用总结 ===\n"); printf("优点:一次系统调用读取多个缓冲区,减少系统调用开销\n"); printf("适用场景:读取结构化数据,协议解析,网络数据包处理\n"); } return 0; }
|