1、关于异步/同步的含义,以及阻塞/非阻塞的含义在上一篇中已经说过了。
在处理I/O的时候,有这么几种方式。同步阻塞、同步非阻塞、异步阻塞、异步非阻塞。
同步阻塞,通常默认的API接口就是同步阻塞的,例如read函数。
同步非阻塞,read是非阻塞的,但是还想同步得到结果通知,当然只能是循环调用read函数知道数据获得为止来实现,相当于同步是程序是自己本身实现了。
异步阻塞,这儿是指读取数据的时候是异步的,在获取通知的时候是阻塞的,是指采用select方式来获取这个设备是否可用,也就是数据是否读取完毕。异步采用的读取接口是aio_read()。
异步非阻塞,是指read非阻塞,而且获取结果结果的时候也是异步的。也是本篇所要说的重点。
2、异步读写的接口,包含aio_read,aio_error,aio_return,aio_write,aio_suspend,aio_cancel,aio_init,lio_listio。
原型分别如下:
2.1读函数,在读的时候,不仅要指定读描述符,而且还要指定程序里需要拷贝的内存的起始地址以及拷贝的长度。函数返回0表示将该结构体加入了读取的队列中,否则返回-1。errno的错误信息和read函数等是一致的。
- int aio_read(struct aiocb *pAioCb);
- /* Asynchronous I/O control block. */
- struct aiocb
- {
- int aio_fildes; /* File desriptor. */
- int aio_lio_opcode; /* Operation to be performed. */
- int aio_reqprio; /* Request priority offset. */
- volatile void *aio_buf; /* Location of buffer. */
- size_t aio_nbytes; /* Length of transfer. */
- struct sigevent aio_sigevent; /* Signal number and value. */
- /* Internal members. */
- struct aiocb *__next_prio;
- int __abs_prio;
- int __policy;
- int __error_code;
- __ssize_t __return_value;
- #ifndef __USE_FILE_OFFSET64
- __off_t aio_offset; /* File offset. */
- char __pad[sizeof (__off64_t) - sizeof (__off_t)];
- #else
- __off64_t aio_offset; /* File offset. */
- #endif
- char __unused[32];
- };
2.2、查询该描述符对应的异步操作是否完成,返回0表示操作结束,EINPROGRESS表示正在进行,ECANCEL表示取消了该操作,否则返回错误。
- int aio_error(struct aiocb* pAioCb);
2.3、查询该操作的返回结果,该操作应该是在aio_error之后调用。返回值的意义和阻塞调用的时候是一样的。
- int aio_return(struct aiocb*pAioCb);
3、获取异步读写结果。获取异步读写结果可以有3中方式。
3.1 通过aio_error来获取当前的读写状态。
3.2 通过设置aiocb结构体里边的aio_sigevent参数中的相应成员来设置获取结果方式为信号驱动。
3.3 通过设置aiocb结构体的边的aio_sigevent参数中的相应成员来设置获取结果方式为回调函数(也就是新起1个新线程,其实和信号驱动的效果是一样的)
4、我写了一个相应的程序,包含了这3种方式,有需要的请见附件。