1.简介:
- 英文缩写 AIO
- linux中常用的是异步IO,它能在等待 IO 请求时不占用 CPU,而异步IO 的意义在于有些时候 IO 请求可能与 其他的进程产生交叠。
- AIO 基本思想是允许进程发起很多 I/O 操作,而不用阻塞或等待任何操作完成。稍后或在接收到 I/O 操作完成的通知时,进程再检索 I/O 操作的结果。
- AID 对IO 的异步阻塞和 select 对通知事件的阻塞功能类似。
- 异步阻塞 IO,允许同时发起多个传输单元,每个传输的所有信息都被保存到 aiocb(AIO I/O Control Block) 结构体中。这个结构体包含了有关传输的所有信息,以及为数据准备的用户缓冲区。在产生 I/O 通知(称为完成)时,aiocb 结构就被用来惟一标识所完成的 I/O 操作。
2. 有关 AIO 的函数:
aio_read :请求对一个有效的文件描述符(可以是一个文件、套接字、管道)进行异步的读
int aio_read( struct aiocb *aiocbp );
立即返回,返回值:
0,成功-1,失败,有error值
aio_write:请求异步的写
int aio_write( struct aiocb *aiocbp );
立即返回,返回值:
0,成功-1,失败,有error值
aio_error:确定请求的状态
int aio_error( struct aiocb *aiocbp );
返回值:
EINPROGRESS,请求尚未完成。ECANCELLED,请求被应用程序取消。-1,发生了错误,具体错误原因由 errno 记录。
aio_return:查询函数状态
因为异步 IO 的返回状态不是立即返回的,因此要用这个函数来查询
ssize_t aio_return( struct aiocb *aiocbp );
此函数一般在 aio_error 这个函数之后。
使用格式:
#include <aio.h>
...
int fd, ret;
struct aiocb my_aiocb;
fd = open("file.txt", O_RDONLY);
if (fd < 0)
perror("open");
/* 清零 aiocb 结构体 */
bzero((char*) &my_aiocb, sizeof(struct aiocb));
/* 为 aiocb 请求分配数据缓冲区 */
my_aiocb.aio_buf = malloc(BUFSIZE + 1);
if (!my_aiocb.aio_buf)
perror("malloc");
/* 初始化 aiocb 的成员 */
my_aiocb.aio_fildes = fd;
my_aiocb.aio_nbytes = BUFSIZE;
my_aiocb.aio_offset = 0;
ret = aio_read(&my_aiocb);
if (ret < 0)
perror("aio_read");
while (aio_error(&my_aiocb) == EINPROGRESS)
continue;
if ((ret = aio_return(&my_iocb)) > 0) {
/* 获得异步读的返回值 */
} else {
/* 读失败,分析 errorno */
}
aio_suspend:挂起或阻塞调用的进程,直到异步请求完成为止,调用者会提供一个 aiocb 引用列表,其中的任何一个完成都会导致 此函数 返回
int aio_suspend( const struct aiocb *const cblist[],
int n,
const struct timespec *timeout );
例子:
用户空间:
struct aioct *cblist[MAX_LIST]
/* 清零 aioct 结构体链表 */
bzero( (char *)cblist, sizeof(cblist) );
/* 将一个或更多的 aiocb 放入 aioct 结构体链表 */
cblist[0] = &my_aiocb;
ret = aio_read( &my_aiocb );
ret = aio_suspend( cblist, MAX_LIST, NULL );
aio_cancel:取消对某个文件描述符的一个或者所有 IO 操作
int aio_cancel( int fd, struct aiocb *aiocbp );
要取消一个请求,要有文件描述符和 aiocb 指针
返回值:
AIO_CANCELED,取消成功,请求未被执行AIO_NOTCANCELED,取消失败,请求被执行了
要取消所有请求,要有文件描述符,aiocbp指针设为 NULL
返回值:
AIO_CANCELED,取消成功AIO_NOT_CANCELED,至少有一个请求未被取消AIO_ALLDONE,没有一个请求被取消
可以使用 aio_error()来验证每个 AIO 请求,如果某请求已经被取消了,那么aio_error()就会返回!1,并且errno 会被设置为 ECANCELED。
lio_listio:同时发起多个传输,使得用户可以在一个系统调用(一次内核上下文切换)中启动大量的 I/O 操作。
int lio_listio( int mode, struct aiocb *list[], int nent, struct sigevent *sig );
参数:
mode,O_WAIT,阻塞这个调用,直到所有 IO 都完成。LIO_NOWAIT,马上返回list[],一个 aiocb 的列表,可为NULLsig,
一个使用 lio_listio 的例子/模板
struct aiocb aiocb1, aiocb2;
struct aiocb *list[MAX_LIST];
...
/* 准备第一个 aiocb */
aiocb1.aio_fildes = fd;
aiocb1.aio_buf = malloc( BUFSIZE+1 );
aiocb1.aio_nbytes = BUFSIZE;
aiocb1.aio_offset = next_offset;
aiocb1.aio_lio_opcode = LIO_READ; /*异步读操作*/
... /*准备多个 aiocb */
bzero( (char *)list, sizeof(list) );
/*将 aiocb 填入链表*/
list[0] = &aiocb1;
list[1] = &aiocb2;
...
ret = lio_listio( LIO_WAIT, list, MAX_LIST, NULL );/*发起大量 I/O 操作*/
说明:
aiocb1.aio_lio_opcode = LIO_READ; /*异步读操作*/ 这句话中操作码的解释:
LIO_READ,进行异步读的操作
LIO_WRITE,进行异步写的操作
LIO_NOP,空操作
可以使用信号、回调函数作为 AIO 的通知
3. 驱动中的实现:
字符设备驱动程序中,file_operations 包含 3 个与 AIO 相关的成员函数:
ssize_t (*aio_read) (struct kiocb *iocb, char *buffer, size_t count, loff_t offset);ssize_t (*aio_write) (struct kiocb *iocb, const char *buffer,size_t count, loff_t offset);int (*aio_fsync) (struct kiocb *iocb, int datasync);
考虑到 AIO 的使用比较少,暂时先整理到这里,等真正的遇到使用的时候,在补充这个地方。