MST

星途 面试题库

面试题:C语言Linux文件I/O异步操作优化

在Linux系统中,使用C语言进行文件I/O操作,当需要处理大量文件读写且要避免阻塞主线程时,如何利用异步I/O来优化性能?请描述具体的实现思路,并给出关键函数及简要代码示例。
14.4万 热度难度
编程语言C

知识考点

AI 面试

面试题答案

一键面试

实现思路

  1. 初始化异步I/O上下文:使用aio_context_t结构体来管理异步I/O操作,通过io_setup函数初始化上下文。
  2. 准备异步I/O请求:填充struct iocb结构体,指定文件描述符、操作类型(读或写)、数据缓冲区、偏移量等信息。
  3. 提交异步I/O请求:使用io_submit函数将iocb结构体提交到异步I/O上下文,让内核开始执行异步操作。
  4. 等待异步I/O完成:使用io_getevents函数等待异步I/O操作完成,并获取操作结果。可以设置超时时间,避免无限期等待。

关键函数

  1. io_setup:初始化异步I/O上下文。
    int io_setup(unsigned nr, aio_context_t *ctxp);
    
    • nr:指定上下文可以处理的最大请求数。
    • ctxp:指向aio_context_t结构体的指针,用于存储初始化后的上下文。
  2. io_destroy:销毁异步I/O上下文。
    int io_destroy(aio_context_t ctx);
    
    • ctx:要销毁的异步I/O上下文。
  3. io_submit:提交异步I/O请求。
    int io_submit(aio_context_t ctx, long nr, struct iocb **iocbpp);
    
    • ctx:异步I/O上下文。
    • nr:要提交的请求数量。
    • iocbpp:指向struct iocb指针数组的指针。
  4. io_getevents:等待异步I/O操作完成并获取结果。
    int io_getevents(aio_context_t ctx, long min_nr, long max_nr, struct io_event *events, struct timespec *timeout);
    
    • ctx:异步I/O上下文。
    • min_nr:最少等待完成的请求数。
    • max_nr:最多获取的完成请求数。
    • events:用于存储完成事件的struct io_event数组。
    • timeout:等待的超时时间,如果为NULL则无限期等待。

代码示例

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <aio.h>
#include <unistd.h>
#include <string.h>

#define BUFFER_SIZE 1024
#define MAX_REQUESTS 10

int main() {
    aio_context_t ctx;
    struct iocb iocbs[MAX_REQUESTS];
    struct io_event events[MAX_REQUESTS];
    char buffers[MAX_REQUESTS][BUFFER_SIZE];
    int file_descriptors[MAX_REQUESTS];
    int num_files = 5;

    // 初始化异步I/O上下文
    if (io_setup(MAX_REQUESTS, &ctx) != 0) {
        perror("io_setup");
        return 1;
    }

    // 打开文件并准备异步I/O请求
    for (int i = 0; i < num_files; i++) {
        char filename[20];
        snprintf(filename, sizeof(filename), "file%d.txt", i);
        file_descriptors[i] = open(filename, O_RDONLY);
        if (file_descriptors[i] == -1) {
            perror("open");
            continue;
        }

        memset(&iocbs[i], 0, sizeof(struct iocb));
        io_prep_pread(&iocbs[i], file_descriptors[i], buffers[i], BUFFER_SIZE, 0);
    }

    // 提交异步I/O请求
    if (io_submit(ctx, num_files, (struct iocb **)&iocbs) != num_files) {
        perror("io_submit");
        goto cleanup;
    }

    // 等待异步I/O完成
    if (io_getevents(ctx, num_files, num_files, events, NULL) != num_files) {
        perror("io_getevents");
        goto cleanup;
    }

    // 处理读取结果
    for (int i = 0; i < num_files; i++) {
        if (events[i].res < 0) {
            perror("read error");
        } else {
            printf("Read %ld bytes from file%d.txt: %.*s\n", events[i].res, i, (int)events[i].res, buffers[i]);
        }
        close(file_descriptors[i]);
    }

cleanup:
    // 销毁异步I/O上下文
    io_destroy(ctx);
    return 0;
}

此代码示例展示了如何使用异步I/O在Linux系统中并行读取多个文件,避免阻塞主线程,从而提高性能。