linux aio (1)



首先推荐这篇文章 http://hi.baidu.com/_kouu/blog/item/e225f67b337841f42f73b341.html


准备分三部分来讲,内核的aio,glibc也就是用户空间的aio,内核aio如何通知用户空间


内核的aio是通过用户态的libaio库开放出去的,libaio其实啥也没做,只是封装了一些系统调用,去调用aio.h/aio.c 中的函数。所有异步IO的请求,在libaio里是一个 struct iocb 结构,对应于内核的 struct kiocb 结构。

aio_run_iocb 是内核 aio 的第一个核心函数,首先调用下 iocb 对应的 retry 函数,如果返回了 EIOCBQUEUED,说明这个 iocb 已经进入了 workqueue,如果返回 EIOCBRETRY,此时这个 iocb 必然后一个 kick 标记,这时会把这个 iocb 加入到 内核的 workqueue 机制中延迟处理。这个 aio_wq 是初始化好的 workqueue,一般而言,对特定的workqueue,每个cpu会对应一个,所以cpu核数的多少对异步IO的性能还是有影响的。

如果iocb被queue了,会启动一个timer,时间到了之后调用 delayed_work_timer_fn,总之 iocb 最终是通过工作队列的方式被执行的。

aio_complete 只有当 iocb 请求结束后会被调用。aio_complete 构造一个iocb完成的 event 放到 aio_ring 里面,最后 wake up 一个 wait_queue_t 结构。

aio_rw_vect_retry 就是前面提到过的 retry 函数,其最终还是去执行 pread/pwrite 之类的调用,该函数会去调用一个 rw_op, 这个函数指针对应的是 file->f_op->aio_read / aio_write, 中间有个循环体会一直重试,只要 iocb->ki_left 还有货没出完,最后一个条件是说,如果操作是 pwritev 同时这个inode 既不是 fifo 也不是 socket , 所以大部分情况下,会需要多次 kick_iocb,而且每次 retry 都返回 EIOCBQUEUED 或者 EIOCBRETRY


aio.c 最后都是定义系统调用的声明:

io_setup:调用 ioctx_alloc 创建一个 struct  kioct

io_destroy: 调用 io_destroy() 同时取消所有未完成的 iocb 请求

io_submit:读取用户空间的 nr 个 iocbpp 指针指向的 struct iocb 结构,对每个iocb 调用 io_submit_one。

io_cancel:调用iocb注册的 cancel 函数,并把结果通过 copy_to_user 返回。

io_getevents:调用 read_events 获取异步IO的完成事件,实际上就是读取 aio_ring 里的 nr 个entry。并通过 copy_to_user返回给用户空间。读取aio_ring 的工作由 aio_read_evt 来完成



  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux AIO(Asynchronous I/O)是一种异步I/O机制,它可以让应用程序在进行I/O操作时,不必等待I/O操作完成才返回,而是在I/O操作进行的同时可以继续执行其他任务。这种机制可以极大地提高I/O操作的效率和应用程序的并发性能。 下面是一个简单的Linux AIO使用示例: ```c #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <aio.h> #include <errno.h> #define BUFSIZE 1024 int main(int argc, char *argv[]) { int fd, ret; char buf[BUFSIZE]; struct aiocb aiocb; // 打开文件 fd = open(argv, O_RDONLY); if (fd < 0) { perror("open"); exit(1); } // 初始化aiocb结构体 bzero(&aiocb, sizeof(struct aiocb)); aiocb.aio_fildes = fd; aiocb.aio_buf = buf; aiocb.aio_nbytes = BUFSIZE; aiocb.aio_offset = 0; // 异步读取文件 ret = aio_read(&aiocb); if (ret < 0) { perror("aio_read"); exit(1); } // 等待异步读取完成 while (aio_error(&aiocb) == EINPROGRESS) { printf("reading...\n"); sleep(1); } // 检查异步读取结果 ret = aio_return(&aiocb); if (ret < 0) { perror("aio_return"); exit(1); } // 输出读取结果 printf("read %d bytes: %s\n", ret, buf); // 关闭文件 close(fd); return 0; } ``` 以上代码会打开指定的文件,异步读取文件内容,等待异步读取完成,输出读取结果,并关闭文件。在这个示例中,aio_read()函数会立即返回,不会阻塞程序运行。如果要进行多个异步I/O操作,可以使用aio_suspend()函数等待所有异步I/O操作完成。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值