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 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315
| #include <linux/aio_abi.h> #include <sys/syscall.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <fcntl.h> #include <time.h>
/** * 系统调用包装函数 */ static inline int io_setup(unsigned nr_events, aio_context_t *ctxp) { return syscall(__NR_io_setup, nr_events, ctxp); }
static inline int io_destroy(aio_context_t ctx) { return syscall(__NR_io_destroy, ctx); }
static inline int io_submit(aio_context_t ctx, long nr, struct iocb **iocbpp) { return syscall(__NR_io_submit, ctx, nr, iocbpp); }
static inline int io_cancel(aio_context_t ctx, struct iocb *iocb, struct io_event *result) { return syscall(__NR_io_cancel, ctx, iocb, result); }
static inline int io_getevents(aio_context_t ctx, long min_nr, long nr, struct io_event *events, struct timespec *timeout) { return syscall(__NR_io_getevents, ctx, min_nr, nr, events, timeout); }
/** * 错误处理上下文 */ typedef struct { int error_code; const char *error_message; int retry_count; int max_retries; time_t error_time; const char *operation_name; } error_context_t;
/** * 记录错误信息 */ void record_error(error_context_t *ctx, int error_code, const char *operation, const char *message) { ctx->error_code = error_code; ctx->error_message = message; ctx->error_time = time(NULL); ctx->operation_name = operation; ctx->retry_count++; printf("错误记录: %s\n", operation); printf(" 错误码: %d\n", error_code); printf(" 错误信息: %s\n", message); printf(" 重试次数: %d/%d\n", ctx->retry_count, ctx->max_retries); }
/** * 错误恢复策略 */ int apply_recovery_strategy(error_context_t *ctx, aio_context_t aio_ctx, struct iocb *iocb) { printf("应用错误恢复策略:\n"); switch (ctx->error_code) { case -EAGAIN: printf(" EAGAIN错误,操作稍后重试\n"); if (ctx->retry_count < ctx->max_retries) { printf(" 重试操作...\n"); struct iocb *iocbs[1] = {iocb}; int ret = io_submit(aio_ctx, 1, iocbs); if (ret == 1) { printf(" ✓ 重试成功\n"); return 0; } else { printf(" ✗ 重试失败: %s\n", strerror(-ret)); record_error(ctx, ret, ctx->operation_name, "重试失败"); } } break; case -ECANCELED: printf(" ECANCELED错误,操作已被取消\n"); printf(" 尝试重新提交操作...\n"); struct iocb *iocbs[1] = {iocb}; int ret = io_submit(aio_ctx, 1, iocbs); if (ret == 1) { printf(" ✓ 重新提交成功\n"); return 0; } else { printf(" ✗ 重新提交失败: %s\n", strerror(-ret)); record_error(ctx, ret, ctx->operation_name, "重新提交失败"); } break; case -EBADF: printf(" EBADF错误,文件描述符无效\n"); printf(" 建议:检查文件描述符有效性\n"); break; case -EINVAL: printf(" EINVAL错误,参数无效\n"); printf(" 建议:检查参数设置\n"); break; default: printf(" 未知错误: %s\n", strerror(-ctx->error_code)); printf(" 建议:记录错误并采取适当措施\n"); break; } return -1; }
/** * 演示错误处理和恢复 */ int demo_error_handling_recovery() { aio_context_t ctx; struct iocb iocb; struct io_event result; int fd; int ret; error_context_t error_ctx = {0}; printf("=== 错误处理和恢复演示 ===\n"); // 设置错误处理上下文 error_ctx.max_retries = 3; error_ctx.retry_count = 0; // 初始化AIO上下文 printf("1. 初始化AIO上下文:\n"); ctx = 0; ret = io_setup(32, &ctx); if (ret < 0) { record_error(&error_ctx, ret, "io_setup", "初始化AIO上下文失败"); apply_recovery_strategy(&error_ctx, ctx, NULL); return -1; } printf(" ✓ AIO上下文初始化成功\n"); // 创建测试文件 printf("\n2. 创建测试文件:\n"); const char *filename = "error_recovery_test.txt"; fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0644); if (fd == -1) { record_error(&error_ctx, -errno, "open", "创建测试文件失败"); io_destroy(ctx); return -1; } printf(" ✓ 测试文件创建成功\n"); // 准备异步写入操作 printf("\n3. 准备异步写入操作:\n"); const char *test_data = "Error handling and recovery test data.\n"; size_t data_size = strlen(test_data); memset(&iocb, 0, sizeof(iocb)); iocb.aio_data = 1001; iocb.aio_lio_opcode = IOCB_CMD_PWRITE; iocb.aio_fildes = fd; iocb.aio_buf = (uint64_t)(uintptr_t)test_data; iocb.aio_nbytes = data_size; iocb.aio_offset = 0; printf(" 准备写入操作:\n"); printf(" 数据大小: %zu 字节\n", data_size); printf(" 用户数据: %llu\n", (unsigned long long)iocb.aio_data); // 提交异步操作 printf("\n4. 提交异步操作:\n"); struct iocb *iocbs[1] = {&iocb}; ret = io_submit(ctx, 1, iocbs); if (ret != 1) { record_error(&error_ctx, ret, "io_submit", "提交异步操作失败"); if (apply_recovery_strategy(&error_ctx, ctx, &iocb) != 0) { close(fd); unlink(filename); io_destroy(ctx); return -1; } } printf(" ✓ 异步操作提交成功\n"); // 演示各种错误场景 printf("\n5. 演示错误场景:\n"); // 场景1: 尝试取消已完成的操作 printf(" 场景1: 尝试取消已完成的操作\n"); struct io_event events[1]; struct timespec timeout = {2, 0}; // 2秒超时 ret = io_getevents(ctx, 1, 1, events, &timeout); if (ret > 0) { printf(" 操作已完成,尝试取消...\n"); ret = io_cancel(ctx, &iocb, &result); if (ret == -EAGAIN) { printf(" ✓ 取消失败:操作已完成 (EAGAIN)\n"); } else if (ret == 0) { printf(" ✓ 操作取消成功\n"); } else { printf(" 取消操作返回: %s\n", strerror(-ret)); } } // 场景2: 使用无效的iocb尝试取消 printf("\n 场景2: 使用无效的iocb尝试取消\n"); struct iocb invalid_iocb; memset(&invalid_iocb, 0, sizeof(invalid_iocb)); invalid_iocb.aio_data = 9999; ret = io_cancel(ctx, &invalid_iocb, &result); if (ret == -EAGAIN) { printf(" ✓ 取消失败:无效操作 (EAGAIN)\n"); } else { printf(" 取消操作返回: %s\n", strerror(-ret)); } // 场景3: 使用无效的上下文ID printf("\n 场景3: 使用无效的上下文ID\n"); struct iocb test_iocb; memset(&test_iocb, 0, sizeof(test_iocb)); aio_context_t invalid_ctx = (aio_context_t)-1; ret = io_cancel(invalid_ctx, &test_iocb, &result); if (ret == -EINVAL) { printf(" ✓ 操作失败:无效上下文ID (EINVAL)\n"); } else { printf(" 取消操作返回: %s\n", strerror(-ret)); } // 场景4: 重复取消同一个操作 printf("\n 场景4: 重复取消操作\n"); ret = io_cancel(ctx, &iocb, &result); if (ret == -EAGAIN) { printf(" ✓ 第二次取消失败:操作已处理 (EAGAIN)\n"); } else if (ret == 0) { printf(" ✓ 第二次取消成功\n"); ret = io_cancel(ctx, &iocb, &result); if (ret == -EAGAIN) { printf(" ✓ 第三次取消失败:操作已处理 (EAGAIN)\n"); } } else { printf(" 第二次取消操作返回: %s\n", strerror(-ret)); } // 演示资源清理错误处理 printf("\n6. 演示资源清理错误处理:\n"); // 正常关闭文件 printf(" 正常关闭文件:\n"); if (close(fd) == 0) { printf(" ✓ 文件关闭成功\n"); } else { record_error(&error_ctx, -errno, "close", "关闭文件失败"); printf(" 尝试强制清理...\n"); } // 删除测试文件 printf(" 删除测试文件:\n"); if (unlink(filename) == 0) { printf(" ✓ 测试文件删除成功\n"); } else { record_error(&error_ctx, -errno, "unlink", "删除测试文件失败"); printf(" 注意:可能需要手动清理测试文件\n"); } // 销毁AIO上下文 printf(" 销毁AIO上下文:\n"); ret = io_destroy(ctx); if (ret == 0) { printf(" ✓ AIO上下文销毁成功\n"); } else { record_error(&error_ctx, ret, "io_destroy", "销毁AIO上下文失败"); printf(" 销毁操作返回: %s\n", strerror(-ret)); } // 显示错误处理总结 printf("\n=== 错误处理总结 ===\n"); printf("1. 常见错误类型:\n"); printf(" ✓ EAGAIN: 操作无法取消(已完成或不存在)\n"); printf(" ✓ EINVAL: 参数无效\n"); printf(" ✓ EBADF: 文件描述符无效\n"); printf(" ✓ ECANCELED: 操作已被取消\n"); printf("\n2. 错误处理策略:\n"); printf(" ✓ 记录错误信息\n"); printf(" ✓ 根据错误类型采取不同措施\n"); printf(" ✓ 必要时重试操作\n"); printf(" ✓ 优雅降级处理\n"); printf("\n3. 恢复策略:\n"); printf(" ✓ 重试机制\n"); printf(" ✓ 备用方案\n"); printf(" ✓ 资源清理\n"); printf(" ✓ 状态恢复\n"); printf("\n4. 最佳实践:\n"); printf(" ✓ 完善的错误记录\n"); printf(" ✓ 适当的重试策略\n"); printf(" ✓ 资源泄漏预防\n"); printf(" ✓ 用户友好提示\n"); return 0; }
int main() { return demo_error_handling_recovery(); }
|