io_destroy 函数详解

io_destroy 函数详解

1. 函数介绍

io_destroy 是Linux传统异步I/O (AIO) 系统调用,用于销毁和清理之前通过 io_setup 创建的异步I/O上下文。它是AIO框架的重要组成部分,负责释放与AIO上下文相关的所有内核资源,包括环形缓冲区、等待队列和其他内部数据结构。

2. 函数原型

#include <linux/aio_abi.h>
#include <sys/syscall.h>
#include <unistd.h>

int io_destroy(aio_context_t ctx);

3. 功能

io_destroy 彻底销毁指定的AIO上下文,释放所有相关的内核资源。在销毁过程中,所有未完成的异步操作都会被取消,相关的事件会被清除,确保系统资源得到正确回收。

4. 参数

  • aio_context_t ctx: 要销毁的AIO上下文ID(由io_setup返回)

5. 返回值

  • 成功: 返回0
  • 失败: 返回负的错误码

6. 相似函数,或关联函数

  • io_setup: 初始化AIO上下文
  • io_submit: 提交异步I/O操作
  • io_cancel: 取消异步I/O操作
  • io_getevents: 获取完成的异步I/O事件
  • close: 关闭文件描述符

7. 示例代码

示例1:基础io_destroy使用

#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>

/**
 * 系统调用包装函数
 */
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);
}

/**
 * 演示基础io_destroy使用方法
 */
int demo_io_destroy_basic() {
    aio_context_t ctx;
    int ret;
    
    printf("=== 基础io_destroy使用示例 ===\n");
    
    // 初始化AIO上下文
    printf("1. 初始化AIO上下文:\n");
    ctx = 0;
    ret = io_setup(128, &ctx);
    if (ret < 0) {
        printf("  初始化AIO上下文失败: %s\n", strerror(-ret));
        return -1;
    }
    printf("  ✓ AIO上下文初始化成功\n");
    printf("  上下文ID: %llu\n", (unsigned long long)ctx);
    
    // 显示上下文信息
    printf("  上下文状态: 已创建\n");
    printf("  缓冲区大小: 128 个事件\n");
    
    // 创建测试文件
    printf("\n2. 创建测试文件:\n");
    const char *filename = "io_destroy_test.txt";
    int fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0644);
    if (fd == -1) {
        perror("  创建测试文件失败");
        io_destroy(ctx);
        return -1;
    }
    printf("  ✓ 测试文件创建成功: %s\n", filename);
    
    // 准备异步写入操作
    printf("\n3. 准备异步写入操作:\n");
    char test_data[] = "Test data for io_destroy demonstration.\n";
    struct iocb iocb;
    
    memset(&iocb, 0, sizeof(iocb));
    iocb.aio_data = 12345;
    iocb.aio_lio_opcode = IOCB_CMD_PWRITE;
    iocb.aio_fildes = fd;
    iocb.aio_buf = (uint64_t)(uintptr_t)test_data;
    iocb.aio_nbytes = strlen(test_data);
    iocb.aio_offset = 0;
    
    printf("  准备异步写入操作:\n");
    printf("    文件描述符: %d\n", fd);
    printf("    数据大小: %zu 字节\n", strlen(test_data));
    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) {
        printf("  提交异步操作失败: %s\n", strerror(-ret));
        close(fd);
        unlink(filename);
        io_destroy(ctx);
        return -1;
    }
    printf("  ✓ 异步操作提交成功\n");
    
    // 等待操作完成
    printf("\n5. 等待操作完成:\n");
    struct io_event events[1];
    struct timespec timeout = {5, 0};  // 5秒超时
    
    ret = io_getevents(ctx, 1, 1, events, &timeout);
    if (ret > 0) {
        printf("  ✓ 操作完成\n");
        printf("    用户数据: %llu\n", (unsigned long long)events[0].data);
        printf("    结果: %ld 字节\n", events[0].res);
        printf("    错误: %ld\n", events[0].res2);
    } else if (ret == 0) {
        printf("  ⚠ 操作超时\n");
    } else {
        printf("  ✗ 等待完成事件失败: %s\n", strerror(-ret));
    }
    
    // 关闭文件
    printf("\n6. 关闭文件:\n");
    close(fd);
    printf("  ✓ 文件关闭成功\n");
    
    // 销毁AIO上下文
    printf("\n7. 销毁AIO上下文:\n");
    printf("  调用: io_destroy(%llu)\n", (unsigned long long)ctx);
    
    ret = io_destroy(ctx);
    if (ret == 0) {
        printf("  ✓ AIO上下文销毁成功\n");
        printf("  上下文状态: 已销毁\n");
    } else {
        printf("  ✗ AIO上下文销毁失败: %s\n", strerror(-ret));
        if (ret == -EINVAL) {
            printf("  原因:无效的上下文ID\n");
        } else if (ret == -EAGAIN) {
            printf("  原因:上下文中仍有未完成的操作\n");
        }
    }
    
    // 清理测试文件
    printf("\n8. 清理测试文件:\n");
    if (unlink(filename) == 0) {
        printf("  ✓ 测试文件清理成功\n");
    } else {
        printf("  ✗ 测试文件清理失败: %s\n", strerror(errno));
    }
    
    return 0;
}

int main() {
    return demo_io_destroy_basic();
}

示例2:资源泄漏检测

#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 <sys/resource.h>

/**
 * 资源使用统计结构
 */
typedef struct {
    unsigned long open_files;
    unsigned long memory_usage_kb;
    unsigned long aio_contexts;
} resource_usage_t;

/**
 * 获取资源使用情况
 */
int get_resource_usage(resource_usage_t *usage) {
    // 获取打开文件数
    struct rlimit rl;
    if (getrlimit(RLIMIT_NOFILE, &rl) == 0) {
        usage->open_files = rl.rlim_cur;
    } else {
        usage->open_files = 0;
    }
    
    // 获取内存使用情况
    FILE *fp = fopen("/proc/self/status", "r");
    if (fp) {
        char line[256];
        while (fgets(line, sizeof(line), fp)) {
            if (strncmp(line, "VmRSS:", 6) == 0) {
                sscanf(line + 6, "%lu", &usage->memory_usage_kb);
                break;
            }
        }
        fclose(fp);
    } else {
        usage->memory_usage_kb = 0;
    }
    
    // 获取AIO上下文信息(简化的模拟)
    usage->aio_contexts = 0;  // 实际应用中需要更复杂的实现
    
    return 0;
}

/**
 * 显示资源使用情况
 */
void show_resource_usage(const char *label, const resource_usage_t *usage) {
    printf("%s:\n", label);
    printf("  打开文件数: %lu\n", usage->open_files);
    printf("  内存使用: %lu KB\n", usage->memory_usage_kb);
    printf("  AIO上下文: %lu\n", usage->aio_contexts);
}

/**
 * 演示资源泄漏检测
 */
int demo_resource_leak_detection() {
    aio_context_t contexts[10];
    resource_usage_t before_usage, after_usage, after_destroy_usage;
    int created_count = 0;
    int destroyed_count = 0;
    
    printf("=== 资源泄漏检测演示 ===\n");
    
    // 获取初始资源使用情况
    printf("1. 获取初始资源使用情况:\n");
    if (get_resource_usage(&before_usage) == 0) {
        show_resource_usage("  初始状态", &before_usage);
    }
    
    // 创建多个AIO上下文
    printf("\n2. 创建多个AIO上下文:\n");
    
    for (int i = 0; i < 10; i++) {
        contexts[i] = 0;
        int ret = io_setup(64, &contexts[i]);
        if (ret == 0) {
            printf("  ✓ 创建AIO上下文 %d: ID=%llu\n", i + 1, (unsigned long long)contexts[i]);
            created_count++;
        } else {
            printf("  ✗ 创建AIO上下文 %d 失败: %s\n", i + 1, strerror(-ret));
        }
    }
    
    printf("  成功创建 %d 个AIO上下文\n", created_count);
    
    // 获取创建后的资源使用情况
    printf("\n3. 获取创建后的资源使用情况:\n");
    sleep(1);  // 等待系统更新资源统计
    
    if (get_resource_usage(&after_usage) == 0) {
        show_resource_usage("  创建后状态", &after_usage);
        
        // 显示资源变化
        if (after_usage.memory_usage_kb > before_usage.memory_usage_kb) {
            printf("  内存使用增加: %lu KB\n", 
                   after_usage.memory_usage_kb - before_usage.memory_usage_kb);
        }
    }
    
    // 销毁部分AIO上下文
    printf("\n4. 销毁部分AIO上下文:\n");
    
    // 销毁前5个上下文
    for (int i = 0; i < 5 && i < created_count; i++) {
        int ret = io_destroy(contexts[i]);
        if (ret == 0) {
            printf("  ✓ 销毁AIO上下文 %d: ID=%llu\n", i + 1, (unsigned long long)contexts[i]);
            destroyed_count++;
            contexts[i] = 0;  // 标记为已销毁
        } else {
            printf("  ✗ 销毁AIO上下文 %d 失败: %s\n", i + 1, strerror(-ret));
        }
    }
    
    printf("  成功销毁 %d 个AIO上下文\n", destroyed_count);
    
    // 获取销毁后的资源使用情况
    printf("\n5. 获取销毁后的资源使用情况:\n");
    sleep(1);  // 等待系统更新资源统计
    
    if (get_resource_usage(&after_destroy_usage) == 0) {
        show_resource_usage("  销毁后状态", &after_destroy_usage);
        
        // 显示资源变化
        if (after_destroy_usage.memory_usage_kb < after_usage.memory_usage_kb) {
            printf("  内存使用减少: %lu KB\n", 
                   after_usage.memory_usage_kb - after_destroy_usage.memory_usage_kb);
        }
        
        if (after_destroy_usage.memory_usage_kb < before_usage.memory_usage_kb) {
            printf("  内存使用净减少: %lu KB\n", 
                   before_usage.memory_usage_kb - after_destroy_usage.memory_usage_kb);
        }
    }
    
    // 销毁剩余的AIO上下文
    printf("\n6. 销毁剩余的AIO上下文:\n");
    
    for (int i = 5; i < created_count; i++) {
        if (contexts[i] != 0) {  // 未被销毁的上下文
            int ret = io_destroy(contexts[i]);
            if (ret == 0) {
                printf("  ✓ 销毁AIO上下文 %d: ID=%llu\n", i + 1, (unsigned long long)contexts[i]);
                destroyed_count++;
            } else {
                printf("  ✗ 销毁AIO上下文 %d 失败: %s\n", i + 1, strerror(-ret));
            }
        }
    }
    
    printf("  总共销毁 %d 个AIO上下文\n", destroyed_count);
    
    // 最终资源使用情况
    printf("\n7. 最终资源使用情况:\n");
    resource_usage_t final_usage;
    sleep(1);  // 等待系统更新资源统计
    
    if (get_resource_usage(&final_usage) == 0) {
        show_resource_usage("  最终状态", &final_usage);
        
        // 资源泄漏检测
        printf("\n8. 资源泄漏检测:\n");
        
        if (final_usage.memory_usage_kb <= before_usage.memory_usage_kb + 100) {
            printf("  ✓ 内存资源回收良好\n");
        } else {
            printf("  ⚠ 可能存在内存泄漏\n");
            printf("    内存使用增加: %lu KB\n", 
                   final_usage.memory_usage_kb - before_usage.memory_usage_kb);
        }
        
        if (final_usage.open_files == before_usage.open_files) {
            printf("  ✓ 文件描述符资源回收良好\n");
        } else {
            printf("  ⚠ 可能存在文件描述符泄漏\n");
        }
    }
    
    // 显示资源管理最佳实践
    printf("\n=== 资源管理最佳实践 ===\n");
    printf("1. 及时销毁:\n");
    printf("   ✓ 使用完AIO上下文后立即销毁\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");
    printf("   ✓ 验证上下文ID的有效性\n");
    printf("   ✓ 避免重复销毁同一上下文\n");
    printf("   ✓ 处理并发访问问题\n");
    
    return 0;
}

int main() {
    return demo_resource_leak_detection();
}

示例3:批量销毁管理

#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>

/**
 * AIO上下文管理器结构
 */
typedef struct {
    aio_context_t contexts[64];
    int context_count;
    int max_contexts;
    time_t creation_time;
    unsigned long total_created;
    unsigned long total_destroyed;
} aio_context_manager_t;

/**
 * 初始化AIO上下文管理器
 */
int init_aio_context_manager(aio_context_manager_t *manager) {
    memset(manager, 0, sizeof(aio_context_manager_t));
    manager->max_contexts = 64;
    manager->creation_time = time(NULL);
    manager->total_created = 0;
    manager->total_destroyed = 0;
    
    printf("AIO上下文管理器初始化完成\n");
    printf("  最大上下文数: %d\n", manager->max_contexts);
    printf("  创建时间: %s", ctime(&manager->creation_time));
    
    return 0;
}

/**
 * 创建AIO上下文
 */
int create_aio_context(aio_context_manager_t *manager, unsigned nr_events, aio_context_t *ctx) {
    if (manager->context_count >= manager->max_contexts) {
        printf("AIO上下文数量已达上限\n");
        return -1;
    }
    
    *ctx = 0;
    int ret = io_setup(nr_events, ctx);
    if (ret == 0) {
        manager->contexts[manager->context_count] = *ctx;
        manager->context_count++;
        manager->total_created++;
        printf("创建AIO上下文成功: ID=%llu\n", (unsigned long long)*ctx);
        return 0;
    } else {
        printf("创建AIO上下文失败: %s\n", strerror(-ret));
        return -1;
    }
}

/**
 * 批量销毁AIO上下文
 */
int batch_destroy_aio_contexts(aio_context_manager_t *manager) {
    printf("批量销毁AIO上下文:\n");
    printf("  当前上下文数量: %d\n", manager->context_count);
    
    int destroyed_count = 0;
    int failed_count = 0;
    
    // 从后往前销毁(避免数组索引问题)
    for (int i = manager->context_count - 1; i >= 0; i--) {
        aio_context_t ctx = manager->contexts[i];
        if (ctx != 0) {
            int ret = io_destroy(ctx);
            if (ret == 0) {
                printf("  ✓ 销毁上下文 %d: ID=%llu\n", i + 1, (unsigned long long)ctx);
                destroyed_count++;
                manager->total_destroyed++;
                
                // 从数组中移除
                for (int j = i; j < manager->context_count - 1; j++) {
                    manager->contexts[j] = manager->contexts[j + 1];
                }
                manager->context_count--;
            } else {
                printf("  ✗ 销毁上下文 %d 失败: %s\n", i + 1, strerror(-ret));
                failed_count++;
            }
        }
    }
    
    printf("批量销毁完成:\n");
    printf("  成功销毁: %d 个\n", destroyed_count);
    printf("  销毁失败: %d 个\n", failed_count);
    printf("  剩余上下文: %d 个\n", manager->context_count);
    
    return (failed_count == 0) ? 0 : -1;
}

/**
 * 销毁所有AIO上下文
 */
int destroy_all_aio_contexts(aio_context_manager_t *manager) {
    printf("销毁所有AIO上下文:\n");
    
    if (manager->context_count == 0) {
        printf("  没有待销毁的上下文\n");
        return 0;
    }
    
    return batch_destroy_aio_contexts(manager);
}

/**
 * 演示批量销毁管理
 */
int demo_batch_destroy_management() {
    aio_context_manager_t manager;
    
    printf("=== 批量销毁管理演示 ===\n");
    
    // 初始化管理器
    printf("1. 初始化AIO上下文管理器:\n");
    if (init_aio_context_manager(&manager) != 0) {
        return -1;
    }
    
    // 创建多个AIO上下文
    printf("\n2. 创建多个AIO上下文:\n");
    
    const int create_count = 10;
    aio_context_t created_contexts[create_count];
    int successful_creates = 0;
    
    for (int i = 0; i < create_count; i++) {
        printf("  创建第 %d 个上下文:\n", i + 1);
        
        if (create_aio_context(&manager, 32, &created_contexts[i]) == 0) {
            successful_creates++;
        } else {
            created_contexts[i] = 0;  // 标记为创建失败
        }
        
        // 短暂延迟以避免系统过载
        if (i < create_count - 1) {
            usleep(10000);  // 10ms延迟
        }
    }
    
    printf("  创建完成:\n");
    printf("    尝试创建: %d 个\n", create_count);
    printf("    成功创建: %d 个\n", successful_creates);
    printf("    创建失败: %d 个\n", create_count - successful_creates);
    printf("    管理器状态: %d 个上下文\n", manager.context_count);
    
    // 显示当前管理器状态
    printf("\n3. 当前管理器状态:\n");
    printf("  总创建数: %lu\n", manager.total_created);
    printf("  总销毁数: %lu\n", manager.total_destroyed);
    printf("  当前上下文数: %d\n", manager.context_count);
    printf("  管理器运行时间: %ld 秒\n", 
           (long)difftime(time(NULL), manager.creation_time));
    
    // 显示所有上下文ID
    printf("  当前上下文ID列表:\n");
    for (int i = 0; i < manager.context_count; i++) {
        printf("    %d: %llu\n", i + 1, (unsigned long long)manager.contexts[i]);
    }
    
    // 批量销毁
    printf("\n4. 批量销毁操作:\n");
    if (destroy_all_aio_contexts(&manager) != 0) {
        printf("  批量销毁过程中出现错误\n");
    }
    
    // 验证销毁结果
    printf("\n5. 验证销毁结果:\n");
    printf("  销毁后状态:\n");
    printf("    当前上下文数: %d\n", manager.context_count);
    printf("    总销毁数: %lu\n", manager.total_destroyed);
    printf("    剩余上下文ID:\n");
    
    if (manager.context_count > 0) {
        for (int i = 0; i < manager.context_count; i++) {
            printf("      %d: %llu\n", i + 1, (unsigned long long)manager.contexts[i]);
        }
        printf("    ⚠ 警告:仍有 %d 个上下文未被销毁\n", manager.context_count);
    } else {
        printf("      无\n");
        printf("    ✓ 所有上下文均已销毁\n");
    }
    
    // 重新创建一些上下文进行最终销毁测试
    printf("\n6. 最终销毁测试:\n");
    
    // 重新创建几个上下文
    printf("  重新创建测试上下文:\n");
    for (int i = 0; i < 3; i++) {
        if (create_aio_context(&manager, 16, &created_contexts[i]) == 0) {
            printf("    重新创建上下文 %d 成功\n", i + 1);
        }
    }
    
    printf("  重新创建后状态:\n");
    printf("    当前上下文数: %d\n", manager.context_count);
    printf("    总创建数: %lu\n", manager.total_created);
    
    // 最终批量销毁
    printf("  执行最终批量销毁:\n");
    if (destroy_all_aio_contexts(&manager) == 0) {
        printf("  ✓ 最终批量销毁成功\n");
    } else {
        printf("  ✗ 最终批量销毁失败\n");
    }
    
    // 显示最终统计
    printf("\n7. 最终统计:\n");
    printf("  管理器生命周期统计:\n");
    printf("    总创建数: %lu\n", manager.total_created);
    printf("    总销毁数: %lu\n", manager.total_destroyed);
    printf("    当前上下文数: %d\n", manager.context_count);
    printf("    运行时间: %ld 秒\n", 
           (long)difftime(time(NULL), manager.creation_time));
    
    if (manager.total_created == manager.total_destroyed && manager.context_count == 0) {
        printf("  ✓ 资源管理完整性检查通过\n");
    } else {
        printf("  ⚠ 资源管理完整性检查失败\n");
        printf("    可能存在资源泄漏\n");
    }
    
    return 0;
}

int main() {
    return demo_batch_destroy_management();
}

示例4:异常情况处理

#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>

/**
 * 系统调用包装函数
 */
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);
}

/**
 * 演示异常情况处理
 */
int demo_exception_handling() {
    aio_context_t ctx;
    int ret;
    
    printf("=== 异常情况处理演示 ===\n");
    
    // 1. 销毁无效的上下文ID
    printf("1. 销毁无效的上下文ID:\n");
    
    // 测试销毁0值上下文ID
    printf("  测试销毁上下文ID 0:\n");
    ret = io_destroy(0);
    if (ret == 0) {
        printf("    ✓ 销毁成功(可能表示空操作)\n");
    } else {
        printf("    %s\n", strerror(-ret));
        if (ret == -EINVAL) {
            printf("    ✓ 预期结果:无效的上下文ID\n");
        } else {
            printf("    ✗ 意外错误\n");
        }
    }
    
    // 测试销毁负值上下文ID
    printf("  测试销毁负值上下文ID (-1):\n");
    ret = io_destroy((aio_context_t)-1);
    if (ret == 0) {
        printf("    ✓ 销毁成功\n");
    } else {
        printf("    %s\n", strerror(-ret));
        if (ret == -EINVAL) {
            printf("    ✓ 预期结果:无效的上下文ID\n");
        } else {
            printf("    ✗ 意外错误\n");
        }
    }
    
    // 测试销毁超大值上下文ID
    printf("  测试销毁超大值上下文ID:\n");
    aio_context_t large_ctx = (aio_context_t)0x7FFFFFFFFFFFFFFFULL;
    ret = io_destroy(large_ctx);
    if (ret == 0) {
        printf("    ✓ 销毁成功\n");
    } else {
        printf("    %s\n", strerror(-ret));
        if (ret == -EINVAL) {
            printf("    ✓ 预期结果:无效的上下文ID\n");
        } else {
            printf("    ✗ 意外错误\n");
        }
    }
    
    // 2. 重复销毁同一上下文
    printf("\n2. 重复销毁同一上下文:\n");
    
    // 创建一个有效的上下文
    printf("  创建有效上下文:\n");
    ctx = 0;
    ret = io_setup(32, &ctx);
    if (ret == 0) {
        printf("    ✓ 上下文创建成功: ID=%llu\n", (unsigned long long)ctx);
        
        // 第一次销毁
        printf("  第一次销毁:\n");
        ret = io_destroy(ctx);
        if (ret == 0) {
            printf("    ✓ 第一次销毁成功\n");
        } else {
            printf("    ✗ 第一次销毁失败: %s\n", strerror(-ret));
        }
        
        // 第二次销毁同一上下文(应该失败)
        printf("  第二次销毁同一上下文:\n");
        ret = io_destroy(ctx);
        if (ret == 0) {
            printf("    ✓ 第二次销毁成功(可能表示幂等操作)\n");
        } else {
            printf("    %s\n", strerror(-ret));
            if (ret == -EINVAL) {
                printf("    ✓ 预期结果:上下文已销毁\n");
            } else {
                printf("    ✗ 意外错误\n");
            }
        }
    } else {
        printf("    ✗ 创建上下文失败: %s\n", strerror(-ret));
    }
    
    // 3. 销毁正在使用的上下文
    printf("\n3. 销毁正在使用的上下文:\n");
    
    // 创建新的上下文
    printf("  创建新上下文:\n");
    ctx = 0;
    ret = io_setup(64, &ctx);
    if (ret == 0) {
        printf("    ✓ 新上下文创建成功: ID=%llu\n", (unsigned long long)ctx);
        
        // 创建测试文件
        const char *filename = "in_use_test.txt";
        int fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0644);
        if (fd != -1) {
            printf("    ✓ 测试文件创建成功\n");
            
            // 准备长时间写入操作
            char *large_data = malloc(1024 * 1024);  // 1MB数据
            if (large_data) {
                // 填充测试数据
                for (int i = 0; i < 1024 * 1024; i++) {
                    large_data[i] = 'A' + (i % 26);
                }
                
                // 准备异步写入操作
                struct iocb iocb;
                memset(&iocb, 0, sizeof(iocb));
                iocb.aio_data = 999;
                iocb.aio_lio_opcode = IOCB_CMD_PWRITE;
                iocb.aio_fildes = fd;
                iocb.aio_buf = (uint64_t)(uintptr_t)large_data;
                iocb.aio_nbytes = 1024 * 1024;
                iocb.aio_offset = 0;
                
                // 提交异步操作
                struct iocb *iocbs[1] = {&iocb};
                ret = io_submit(ctx, 1, iocbs);
                if (ret == 1) {
                    printf("    ✓ 异步写入操作提交成功\n");
                    
                    // 立即尝试销毁上下文
                    printf("  立即尝试销毁正在使用的上下文:\n");
                    ret = io_destroy(ctx);
                    if (ret == 0) {
                        printf("    ✓ 上下文销毁成功\n");
                    } else {
                        printf("    %s\n", strerror(-ret));
                        if (ret == -EAGAIN) {
                            printf("    ✓ 预期结果:上下文正在使用中\n");
                        } else if (ret == -EINVAL) {
                            printf("    ✓ 预期结果:上下文无效\n");
                        } else {
                            printf("    ✗ 意外错误\n");
                        }
                    }
                } else {
                    printf("    ✗ 提交异步操作失败: %s\n", strerror(-ret));
                }
                
                free(large_data);
            }
            
            close(fd);
            unlink(filename);
        }
    } else {
        printf("    ✗ 创建新上下文失败: %s\n", strerror(-ret));
    }
    
    // 4. 错误恢复演示
    printf("\n4. 错误恢复演示:\n");
    
    // 模拟错误恢复场景
    printf("  错误恢复策略:\n");
    printf("    1. 验证上下文ID有效性\n");
    printf("    2. 检查上下文使用状态\n");
    printf("    3. 尝试取消未完成操作\n");
    printf("    4. 安全销毁上下文\n");
    printf("    5. 记录错误日志\n");
    printf("    6. 通知上层应用\n");
    
    // 5. 资源清理验证
    printf("\n5. 资源清理验证:\n");
    
    // 创建多个上下文用于清理验证
    aio_context_t test_contexts[5];
    int created_count = 0;
    
    printf("  创建测试上下文:\n");
    for (int i = 0; i < 5; i++) {
        test_contexts[i] = 0;
        ret = io_setup(16, &test_contexts[i]);
        if (ret == 0) {
            printf("    ✓ 上下文 %d 创建成功: ID=%llu\n", 
                   i + 1, (unsigned long long)test_contexts[i]);
            created_count++;
        } else {
            printf("    ✗ 上下文 %d 创建失败: %s\n", i + 1, strerror(-ret));
            test_contexts[i] = 0;  // 标记为未创建
        }
    }
    
    printf("  清理所有测试上下文:\n");
    int destroyed_count = 0;
    int error_count = 0;
    
    for (int i = 0; i < 5; i++) {
        if (test_contexts[i] != 0) {
            ret = io_destroy(test_contexts[i]);
            if (ret == 0) {
                printf("    ✓ 上下文 %d 销毁成功\n", i + 1);
                destroyed_count++;
            } else {
                printf("    ✗ 上下文 %d 销毁失败: %s\n", i + 1, strerror(-ret));
                error_count++;
            }
        }
    }
    
    printf("  清理结果:\n");
    printf("    成功销毁: %d 个\n", destroyed_count);
    printf("    销毁失败: %d 个\n", error_count);
    printf("    总计处理: %d 个\n", destroyed_count + error_count);
    
    // 6. 最终状态检查
    printf("\n6. 最终状态检查:\n");
    printf("  系统状态:\n");
    printf("    ✓ 错误处理机制正常\n");
    printf("    ✓ 资源清理机制正常\n");
    printf("    ✓ 状态恢复机制正常\n");
    printf("    ✓ 日志记录机制正常\n");
    
    return 0;
}

int main() {
    return demo_exception_handling();
}

示例5:生产环境使用模式

#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 <pthread.h>
#include <signal.h>
#include <sys/time.h>

/**
 * 生产环境AIO上下文管理器
 */
typedef struct {
    aio_context_t ctx;
    int is_initialized;
    int is_destroyed;
    time_t create_time;
    time_t destroy_time;
    unsigned long operations_submitted;
    unsigned long operations_completed;
    unsigned long operations_cancelled;
    pthread_mutex_t mutex;
    volatile int shutdown_requested;
} production_aio_context_t;

/**
 * 系统调用包装函数
 */
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, iocbsp);
}

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);
}

/**
 * 初始化生产环境AIO上下文
 */
int init_production_aio_context(production_aio_context_t *ctx, unsigned nr_events) {
    // 初始化结构体
    memset(ctx, 0, sizeof(production_aio_context_t));
    ctx->create_time = time(NULL);
    ctx->is_initialized = 0;
    ctx->is_destroyed = 0;
    ctx->shutdown_requested = 0;
    
    // 初始化互斥锁
    if (pthread_mutex_init(&ctx->mutex, NULL) != 0) {
        printf("初始化互斥锁失败\n");
        return -1;
    }
    
    // 创建AIO上下文
    ctx->ctx = 0;
    int ret = io_setup(nr_events, &ctx->ctx);
    if (ret != 0) {
        printf("创建AIO上下文失败: %s\n", strerror(-ret));
        pthread_mutex_destroy(&ctx->mutex);
        return -1;
    }
    
    ctx->is_initialized = 1;
    printf("生产环境AIO上下文初始化成功:\n");
    printf("  上下文ID: %llu\n", (unsigned long long)ctx->ctx);
    printf("  缓冲区大小: %u 事件\n", nr_events);
    printf("  创建时间: %s", ctime(&ctx->create_time));
    
    return 0;
}

/**
 * 安全销毁生产环境AIO上下文
 */
int destroy_production_aio_context(production_aio_context_t *ctx) {
    if (!ctx) {
        printf("上下文指针无效\n");
        return -1;
    }
    
    // 获取互斥锁
    if (pthread_mutex_lock(&ctx->mutex) != 0) {
        printf("获取互斥锁失败\n");
        return -1;
    }
    
    // 检查是否已经销毁
    if (ctx->is_destroyed) {
        printf("上下文已销毁,无需重复操作\n");
        pthread_mutex_unlock(&ctx->mutex);
        return 0;
    }
    
    // 设置关闭请求标志
    ctx->shutdown_requested = 1;
    
    // 取消所有未完成的操作
    printf("取消所有未完成的操作...\n");
    // 这里应该实现取消未完成操作的逻辑
    
    // 销毁AIO上下文
    printf("销毁AIO上下文: %llu\n", (unsigned long long)ctx->ctx);
    int ret = io_destroy(ctx->ctx);
    if (ret != 0) {
        printf("销毁AIO上下文失败: %s\n", strerror(-ret));
        if (ret == -EAGAIN) {
            printf("  原因:上下文中仍有未完成的操作\n");
        } else if (ret == -EINVAL) {
            printf("  原因:无效的上下文ID\n");
        }
        
        // 即使销毁失败也要清理资源
        ctx->is_destroyed = 1;
        ctx->destroy_time = time(NULL);
        pthread_mutex_unlock(&ctx->mutex);
        pthread_mutex_destroy(&ctx->mutex);
        return -1;
    }
    
    ctx->is_destroyed = 1;
    ctx->destroy_time = time(NULL);
    
    // 显示统计信息
    printf("AIO上下文销毁成功:\n");
    printf("  销毁时间: %s", ctime(&ctx->destroy_time));
    printf("  运行时间: %ld 秒\n", 
           (long)difftime(ctx->destroy_time, ctx->create_time));
    printf("  提交操作数: %lu\n", ctx->operations_submitted);
    printf("  完成操作数: %lu\n", ctx->operations_completed);
    printf("  取消操作数: %lu\n", ctx->operations_cancelled);
    
    pthread_mutex_unlock(&ctx->mutex);
    pthread_mutex_destroy(&ctx->mutex);
    
    return 0;
}

/**
 * 优雅关闭信号处理
 */
void graceful_shutdown_handler(int sig) {
    printf("\n收到关闭信号 %d,开始优雅关闭...\n", sig);
    // 这里应该通知所有AIO上下文管理器开始关闭
}

/**
 * 演示生产环境使用模式
 */
int demo_production_usage_pattern() {
    production_aio_context_t aio_ctx;
    struct sigaction sa;
    
    printf("=== 生产环境使用模式演示 ===\n");
    
    // 设置信号处理
    printf("1. 设置信号处理:\n");
    memset(&sa, 0, sizeof(sa));
    sa.sa_handler = graceful_shutdown_handler;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;
    
    if (sigaction(SIGINT, &sa, NULL) == 0) {
        printf("  ✓ SIGINT信号处理设置成功\n");
    } else {
        printf("  ✗ SIGINT信号处理设置失败: %s\n", strerror(errno));
    }
    
    if (sigaction(SIGTERM, &sa, NULL) == 0) {
        printf("  ✓ SIGTERM信号处理设置成功\n");
    } else {
        printf("  ✗ SIGTERM信号处理设置失败: %s\n", strerror(errno));
    }
    
    // 初始化AIO上下文
    printf("\n2. 初始化生产环境AIO上下文:\n");
    if (init_production_aio_context(&aio_ctx, 1024) != 0) {
        printf("初始化生产环境AIO上下文失败\n");
        return -1;
    }
    
    printf("  ✓ 生产环境AIO上下文初始化成功\n");
    
    // 模拟生产环境操作
    printf("\n3. 模拟生产环境操作:\n");
    
    // 模拟提交操作
    printf("  模拟提交异步操作:\n");
    for (int i = 0; i < 100; i++) {
        // 这里应该是实际的异步操作提交
        aio_ctx.operations_submitted++;
        
        if (i % 20 == 0) {
            printf("    已提交 %d 个操作\n", i);
        }
        
        // 模拟操作完成
        if (i % 3 == 0) {
            aio_ctx.operations_completed++;
        }
        
        // 模拟操作取消
        if (i % 7 == 0) {
            aio_ctx.operations_cancelled++;
        }
    }
    
    printf("  ✓ 模拟操作完成\n");
    printf("    总提交: %lu\n", aio_ctx.operations_submitted);
    printf("    总完成: %lu\n", aio_ctx.operations_completed);
    printf("    总取消: %lu\n", aio_ctx.operations_cancelled);
    
    // 模拟运行期间的状态监控
    printf("\n4. 模拟运行期间状态监控:\n");
    
    // 显示当前状态
    printf("  当前AIO上下文状态:\n");
    printf("    已初始化: %s\n", aio_ctx.is_initialized ? "是" : "否");
    printf("    已销毁: %s\n", aio_ctx.is_destroyed ? "是" : "否");
    printf("    关闭请求: %s\n", aio_ctx.shutdown_requested ? "是" : "否");
    printf("    运行时间: %ld 秒\n", 
           (long)difftime(time(NULL), aio_ctx.create_time));
    
    // 模拟健康检查
    printf("  健康检查:\n");
    printf("    ✓ 上下文ID有效性检查\n");
    printf("    ✓ 内存使用情况检查\n");
    printf("    ✓ 操作队列状态检查\n");
    printf("    ✓ 错误率统计检查\n");
    
    // 模拟优雅关闭
    printf("\n5. 模拟优雅关闭:\n");
    
    // 设置关闭标志
    printf("  设置关闭标志:\n");
    aio_ctx.shutdown_requested = 1;
    printf("    ✓ 关闭请求已设置\n");
    
    // 等待未完成操作
    printf("  等待未完成操作:\n");
    printf("    当前未完成操作数: %lu\n", 
           aio_ctx.operations_submitted - 
           aio_ctx.operations_completed - 
           aio_ctx.operations_cancelled);
    
    // 取消未完成操作
    printf("  取消未完成操作:\n");
    unsigned long pending_operations = aio_ctx.operations_submitted - 
                                      aio_ctx.operations_completed - 
                                      aio_ctx.operations_cancelled;
    printf("    取消 %lu 个未完成操作\n", pending_operations);
    aio_ctx.operations_cancelled += pending_operations;
    
    // 销毁AIO上下文
    printf("  销毁AIO上下文:\n");
    if (destroy_production_aio_context(&aio_ctx) == 0) {
        printf("    ✓ AIO上下文销毁成功\n");
    } else {
        printf("    ✗ AIO上下文销毁失败\n");
    }
    
    // 显示最终统计
    printf("\n6. 最终统计:\n");
    printf("  生命周期统计:\n");
    printf("    创建时间: %s", ctime(&aio_ctx.create_time));
    if (aio_ctx.is_destroyed) {
        printf("    销毁时间: %s", ctime(&aio_ctx.destroy_time));
        printf("    运行时间: %ld 秒\n", 
               (long)difftime(aio_ctx.destroy_time, aio_ctx.create_time));
    }
    
    printf("  操作统计:\n");
    printf("    总提交操作: %lu\n", aio_ctx.operations_submitted);
    printf("    总完成操作: %lu\n", aio_ctx.operations_completed);
    printf("    总取消操作: %lu\n", aio_ctx.operations_cancelled);
    
    // 显示生产环境最佳实践
    printf("\n=== 生产环境最佳实践 ===\n");
    printf("1. 初始化管理:\n");
    printf("   ✓ 延迟初始化\n");
    printf("   ✓ 配置验证\n");
    printf("   ✓ 资源预留\n");
    printf("   ✓ 错误恢复\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");
    
    printf("\n5. 监控告警:\n");
    printf("   ✓ 性能指标\n");
    printf("   ✓ 错误率统计\n");
    printf("   ✓ 资源使用率\n");
    printf("   ✓ 健康检查\n");
    
    return 0;
}

int main() {
    return demo_production_usage_pattern();
}

io_destroy 使用注意事项

系统要求:

  1. 内核版本: 支持AIO的Linux内核
  2. 权限要求: 通常不需要特殊权限
  3. 架构支持: 支持所有主流架构

销毁时机:

  1. 使用完成后: AIO上下文不再需要时立即销毁
  2. 程序退出前: 确保所有上下文都被正确销毁
  3. 异常处理: 异常情况下也要销毁上下文

错误处理:

  1. EINVAL: 无效的上下文ID
  2. EAGAIN: 上下文中仍有未完成的操作
  3. EFAULT: 上下文指针无效

资源管理:

  1. 及时销毁: 避免资源泄漏
  2. 批量销毁: 提高销毁效率
  3. 状态检查: 销毁前检查上下文状态
  4. 错误恢复: 处理销毁失败的情况

性能考虑:

  1. 销毁开销: 销毁操作有一定开销
  2. 批量操作: 批量销毁比单独销毁更高效
  3. 异步销毁: 大量上下文时考虑异步销毁
  4. 资源回收: 及时回收系统资源

安全考虑:

  1. 权限验证: 确保有权限销毁上下文
  2. 参数验证: 验证上下文ID的有效性
  3. 状态检查: 检查上下文使用状态
  4. 并发控制: 多线程环境下的同步控制

最佳实践:

  1. RAII原则: 使用完立即销毁
  2. 异常安全: 异常情况下也能正确销毁
  3. 资源统计: 统计和监控资源使用情况
  4. 日志记录: 记录销毁操作日志
  5. 错误处理: 妥善处理销毁失败的情况

io_destroy vs 相似函数对比

io_destroy vs close:

// io_destroy: 销毁AIO上下文
io_destroy(ctx);

// close: 关闭文件描述符
close(fd);

io_destroy vs free:

// io_destroy: 销毁内核资源
io_destroy(ctx);

// free: 释放用户空间内存
free(ptr);

常见使用场景

1. 服务器应用:

// 服务器退出时销毁所有AIO上下文
void server_shutdown() {
    for (int i = 0; i < context_count; i++) {
        io_destroy(contexts[i]);
    }
}

2. 批处理应用:

// 批处理完成后销毁AIO上下文
void batch_cleanup() {
    batch_destroy_aio_contexts(&manager);
}

3. 插件系统:

// 插件卸载时销毁相关AIO上下文
void plugin_unload() {
    destroy_plugin_aio_contexts();
}

系统限制和约束

1. 上下文数量限制:

// 系统限制可通过以下方式查看:
cat /proc/sys/fs/aio-max-nr    # 最大AIO上下文数
cat /proc/sys/fs/aio-nr        # 当前AIO上下文数

2. 内存限制:

// 每个AIO上下文都有内存开销
// 需要合理控制上下文数量

3. 文件描述符限制:

// AIO操作涉及的文件描述符也需要管理
// 避免文件描述符泄漏

错误恢复策略

1. 重试机制:

int safe_io_destroy(aio_context_t ctx) {
    int retries = 3;
    int result;
    
    while (retries-- > 0) {
        result = io_destroy(ctx);
        if (result == 0) {
            return 0;  // 成功
        }
        
        if (result == -EAGAIN) {
            // 等待未完成操作
            usleep(100000);  // 100ms
            continue;
        }
        
        break;  // 其他错误不重试
    }
    
    return result;
}

2. 状态检查:

int validate_context_before_destroy(aio_context_t ctx) {
    // 检查上下文是否有效
    if (ctx == 0) {
        return -1;  // 无效上下文
    }
    
    // 检查上下文是否已被销毁
    // 这需要应用层维护状态
    
    return 0;
}

3. 资源清理:

int comprehensive_cleanup(aio_context_t ctx) {
    // 取消所有未完成操作
    cancel_pending_operations(ctx);
    
    // 等待操作完成
    wait_for_operations_completion(ctx);
    
    // 销毁上下文
    return io_destroy(ctx);
}

总结

io_destroy 是Linux AIO框架中重要的资源清理函数,提供了:

  1. 资源回收: 释放AIO上下文相关的内核资源
  2. 内存管理: 回收环形缓冲区和其他数据结构
  3. 状态清理: 清理上下文相关的等待队列和状态
  4. 安全保障: 确保系统资源得到正确回收

通过合理使用 io_destroy,可以构建健壮的异步I/O应用。在实际应用中,需要注意资源管理、错误处理和性能优化等关键问题。特别是在生产环境中,需要实现完善的错误恢复和优雅关闭机制,确保系统的稳定性和可靠性。

此条目发表在未分类分类目录。将固定链接加入收藏夹。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注