Linux AIO

libaio

Linux从2.6的kernel开始提供aoi,系统调用的直接使用是通过汇编,使用int中断指令或者专用的syscall指令,但是gnu的glibc没有提供aoi系统调用的c语言调用封装,oracle提供了一个简单封装libaio。
主要有5个调用配合使用。

  • int io_setup(unsigned nr_events, aio_context_t *ctxp);

//linux/aio_abi.h

typedef unsigned long aio_context_t;

创建内核中的ctx,用户空间得到ctx的id,通过long*操作

  • asmlinkage long sys_io_submit(aio_context_t ctx_id, long nr, struct iocb __user * __user *iocbpp)
  • asmlinkage long sys_io_getevents(aio_context_t ctx_id, long min_nr, long nr, struct io_event __user *events, struct timespec __user *timeout)

参数:

(1)ctx_id:AIO上下文句柄;

(2)min_nr:至少收集min_nr个已经完成的IO请求才返回;

(3)nr:最多收集nr个已经完成的IO请求;

(4)timeout:等待的时间

(5)events:由应用层分配,内核将完成的io_event拷贝到该缓冲区,所以,events数组要保证至少有nr个io_event。

  • io_getevent
  • io_cancel

glibc的假异步io

glibc通过线程处理io请求实现假的异步io,性能感人。

else point

  • O_DIRECT表示直接访问directly access disk,也就是没有cache,不是所有的文件系统都支持真正的directly,通过这种方式打开fd使用AIO才有意义

  • epoll中的e表示event。

epoll中的epoll_wait是阻塞的。可以发现在等待结果的时候大多数api或者syscall都是阻塞的。

阻塞io到非阻塞io到aio的发展逻辑

最开始只有阻塞io,首先open调用得到的fd,然后read(fd,data)/write(fd,data),不一定是随时都是可以rw的,阻塞的时候当前线程无法推进,任务完成受阻。

  • select/poll
    所有多了一个select/poll可以用来查询哪些fd是可以立即rw的,不需要被阻塞,只有select、poll的时候被阻塞。

  • epoll
    监听或者查询的fd的集合每次都要从用户空间复制到内核,而epoll不需要复制整个集合,因为等价功能的数据本来就保存在内核空间

  • aio
    虽然select poll epoll省去了fd可以rw之前的等待时间,但是后续在整个read和write的调用过程中,还是必须针对每一个fd的read、write完成才会返回。aio在write的时候io_submit提交一个write请求,立即就返回了,不用等内核把数据真正写出去,而真正是否写出去的结果,通过io_getevent,只有这个是阻塞的,也可以设置timeout。
    所以aio真正指的是真正的read和write的过程。也就是data从mem到外设的过程不阻塞进程。

posted on 2019-03-04 19:03  还好可以改名字  阅读(659)  评论(0编辑  收藏  举报