异步IO

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 的列表,可为NULL

sig,

一个使用 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 的使用比较少,暂时先整理到这里,等真正的遇到使用的时候,在补充这个地方。




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值