索鸟网

  1. 首页
  2. C中异步IO浅析之二:基于libaio的异步IO

C中异步IO浅析之二:基于libaio的异步IO


在实际的文件系统等高并发度的场景中,用得更多的是异步IO模式还是基于libaio。下面简要介绍基于libaio的实现。

 

1 安装依赖头文件和库

 

由于libaio不是centos原生的支持,需要手动安装开发库:

 

[root@localhost test]# yum install libaio.x86_64 libaio-devel.x86_64

 

2 理解主要的数据结构和API

 

主要的内容在:/usr/include/libaio.h



显然从上面的iocb数据结构能看出:它支持单个的io操作(io_iocb_common),也支持成批的IO处理(io_iocb_vector),还支持基于polling 模式。

 

为了便于实际调用,避免对内部数据结构初始化的麻烦,它还封装好了多个常用的inline函数,这些inline函数基本上可以理解成宏:

 

static inline int io_fsync(io_context_t ctx, struct iocb *iocb, io_callback_t cb, int fd)

{

    io_prep_fsync(iocb, fd);

    io_set_callback(iocb, cb);

    return io_submit(ctx, 1, &iocb);

}

 

static inline void io_prep_fdsync(struct iocb *iocb, int fd)

{

    memset(iocb, 0, sizeof(*iocb));

    iocb->aio_fildes = fd;

    iocb->aio_lio_opcode = IO_CMD_FDSYNC;

    iocb->aio_reqprio = 0;

}

 

static inline int io_fdsync(io_context_t ctx, struct iocb *iocb, io_callback_t cb, int fd)

{

    io_prep_fdsync(iocb, fd);

    io_set_callback(iocb, cb);

    return io_submit(ctx, 1, &iocb);

}

 

不同于上一篇博客中提到的那种异步IO通过信号机制实现异步,libaio主要用event 来实现异步:一个IO初始化的时候对应一个io event, 每完成一个IO就产生一个event, 因此IO 请求提交之后,随时检查返回的io event的数量,就知道哪些IO已经完成。

 

static inline void io_set_eventfd(struct iocb *iocb, int eventfd)

{

    iocb->u.c.flags |= (1 << 0) /* IOCB_FLAG_RESFD */;

    iocb->u.c.resfd = eventfd;

}

 

3. 注意事项


3.1  aio context 数据结构在调用之前必须清0;

 DESCRIPTION

       The  io_setup()  system  call  creates an asynchronous I/O context suitable for concurrently processing nr_events operations.  The ctx_idp argument must not

       point to an AIO context that already exists, and must be initialized to 0 prior to the call.  On successful creation of the AIO context, *ctx_idp is  filled

       in with the resulting handle.

 

 

3.2  aio context system call : io_submit/io_setup 系统调用等不能直接使用,需要调用wrapper().

 

 Note that the libaio wrapper function uses a different type (io_context_t *) for the ctx_idp argument.  Note also that the libaio wrapper  does  not  follow

       the  usual C library conventions for indicating errors: on error it returns a negated error number (the negative of one of the values listed in ERRORS).  If

       the system call is invoked via syscall(2), then the return value follows the usual conventions for indicating an error: -1, with errno set to  a  (positive)

       value that indicates the error.

 

3.3 注意数据结构的区别

aio_context_t 只在libaio.h 中有定义;

而io_context_t 只是在linux/aio_abi.h 和 aio.h中有定义。

 

4. 如何实现事件传递和异步

 

实际文件系统中常见的用法:

memset(&myctx, 0, sizeof(myctx)) 初始化有ioctx;

io_queue_init(AIO_MAXIO, &myctx); 第一个参数指定了IO数目吧

 

io_prep_pread()/ io_prep_pwrite()

io_set_callback(io, callbak); //  设置IO完成之后的回调函数

 

io_submit()提交一组IO 请求;

io_getevents()得到已经执行完的IO数目及其状态。

 

io_run_queue()

io_wait_queue()

 

5. 编译

不能再像自带的aio库一样依赖librt了,否则编译过程当会出现类似下面的错误:

[root@localhost test]# gcc -o libaio_test libaio_test.c  -lrt

/tmp/ccXHzl0H.o: In function `main":

libaio_test.c:(.text+0x62): undefined reference to `io_setup"

libaio_test.c:(.text+0x8f): undefined reference to `io_prep_pwrite"

libaio_test.c:(.text+0xae): undefined reference to `io_fsync"

collect2: error: ld returned 1 exit status

 

而应该用libaio:

gcc -o libaio_test libaio_test.c  -laio (库在/lib64下面:./lib64/libaio.so.1) 连接到linux的libaio.so库。

 

 

6. 参考链接

http://blog.csdn.net/ixidof/article/details/51211508

http://blog.csdn.net/zhaofuguang/article/details/12853881

http://blog.csdn.net/zhaofuguang/article/details/12853883

 

 

 

 

 


C 异步IO libaio

来源地址:http://xiamachao.blog.51cto.com/10580956/1969902 版权归作者所有!

相关教程

  • C中异步IO浅析之一:基于AIO_ABI的异步IO

    相较于同步IO,异步IO请求发出后,应用程序不用阻塞,可以继续执行后面的业务流程,因此能够极大提高系统并发度和吞吐率。这也是为何许多SAN服务后端数据落盘常常采用异步IO读写的原因。 C语言中提供了两套实现异步IO的方法,根据个人的理解,可以分为原生的AIO_ABI方法和集成的libaio方法。这篇主要介绍原生的异步IO的使用方法。 1. 头文件和原生异步IO
  • 基于swoole与php协程实现异步非阻塞IO

    本文由neuSnail在segmentfault发表,未经允许严禁转载,原文地址 本文协程调度的实现参考了有赞的zanphp实现:http://zanphp.io/ 自己写了一个简单的swoole+php协程的框架:https://github.com/neuSnail/Pcs有兴趣的可以看看,很不成熟欢迎指教。 Pcs是我参考zanphp做的毕业设计,
  • Linux下 fio磁盘压测笔记

    专业的测试磁盘IO性能的软件:1、fio 【推荐使用】2、iometerfio的使用:参考博客: http://lilinji.blog.51cto.com/5441000/1569623https://linux.die.net/man/1/fiohttp://elf8848.iteye.com/blog/2168876   【讲的比较好】注意,我先使用yum安装的f
  • PHP异步编程,异步的本质

    实现异步的方式有哪些? swoole提供了一些异步方法, 那它们底层是用哪种方式实现的呢? 实现异步的方式有: 线程方式 进程方式 IO复用 线程方式和进程方式类似, 有异步请求时, 开一个线程或者进程, 获取到数据后, 线程间可以直接共享数据. 进程间可以通过进程通信机制,如共享内存,管道等方式进行数据传送. 思路很简单, 可以参考这篇利用swoo
  • IO系统

    IO种类:文件、控制台、网络连接 1.字节流 1.1InputStream子类简单说明: ByteArrayInputStream:包含一个内部缓冲区,该缓冲区中包含从流中读取的字节 FileInputStream:从文件系统的某个文件中获得输入字节,可以通过String、File或FileDescriptor 作为数据源使用 FilterIn
  • IO分类

    分类 IO的分类,从两个角度可以分为:阻塞/非阻塞 & 同步/异步。如果进行细分,可以衍生出4种组合:同步阻塞、异步非阻塞….通常很少有人会去细究,阻塞和同步也是混着叫。本次总结基本就是要扣细节。 要想分得清,得明白这两种分类是对什么分的类,分类依据是什么。 分类 分类对象 分类依据 阻塞/非阻塞 IO接口 是否需
  • ES6&ES7中的异步之Generator函数与异步编程

    Generator函数与异步编程 因为js是单线程语言,所以需要异步编程的存在,要不效率太低会卡死。 传统的异步方法 回调函数 事件监听 发布/订阅 Promise 之前写过一篇关于Promise的文章,里边写过关于异步的一些概念。这篇文章将会说一下Generator函数的异步应用。 Generator函数 协程 多个线程互相合作完成任务,在传统的编
  • Java IO

    主要内容 java.io.File类的使用 IO原理及流的分类 文件流 FileInputStream / FileOutputStream / FileReader / FileWriter 缓冲流 BufferedInputStream / BufferedOutputStream / BufferedReader / BufferedWr