中文
注册
我要评分
文档获取效率
文档正确性
内容完整性
文档易理解
在线提单
论坛求助
鲲鹏小智

libaio实现参考

对于磁盘文件,文件的读取是同步的,导致线程读取文件时,属于阻塞状态。程序为了提升性能和磁盘的吞吐,程序会创建几个单独的磁盘读写线程,并通过信号量等机制进行线程间通信(同时带有锁);显然线程多,锁多,会导致更多的资源抢占,从而导致系统整体性能下降。

libaio提供了磁盘文件读写的异步机制,使得文件读写不用阻塞,结合epoll机制,实现一个线程可以无阻塞的运行,同时处理多个文件读写请求,提升服务器整体性能。下面是libaio+epoll的一个实现示例。

代码删除了变量初始化、异常判断等分支。

/* AIO的回调函数*/
void aio_callback(io_context_t ctx, struct iocb *iocb, long res, long res2)
{
    /* 失败时-res为errorno;成功时,res为真正读取的字节数;
       iocb->u.c.buf为读取的内容*/
    ···
}

/*
 * 使用libaio和epoll,对同一个文件的若干个不同偏移位置发起异步读取请求,
 * 如对文件的偏移位置0、1024*1、1024*2、、1024*127发起总共128个异步读取请求(读取1024字节)
 */
int libaio_epoll_read_file()
{
    efd = eventfd(0, EFD_NONBLOCK);
    fd = open(TEST_FILE, O_RDWR | O_CREAT | O_DIRECT, 0644);
    io_setup(8192, &ctx);
    for (int i = 0; i < NUM_EVENTS; i++) {
        posix_memalign(&buf, ALIGN_SIZE, RD_WR_SIZE);
        io_prep_pread(iocbs[i], fd, buf, RD_WR_SIZE, i * RD_WR_SIZE);
        io_set_eventfd(iocbs[i], efd);
        io_set_callback(iocbs[i], aio_callback);
    }
    io_submit(ctx, NUM_EVENTS, iocbs);
    epfd = epoll_create(1);
    epevent.events = EPOLLIN | EPOLLET;
    epevent.data.ptr = NULL;
    epoll_ctl(epfd, EPOLL_CTL_ADD, efd, &epevent);
    while (i < NUM_EVENTS) {
        epoll_wait(epfd, &epevent, 1, -1);
        read(efd, &finished_aio, sizeof(finished_aio));
        while (finished_aio > 0) {
            r = io_getevents(ctx, 1, NUM_EVENTS, events, &tms);
            for (j = 0; j < r; ++j) {
                // 调用对应事件的回调函数,处理数据
                ((io_callback_t)(events[j].data))(
                    ctx, events[j].obj, events[j].res, events[j].res2);
            }
        }
    }
}