异步IO基本API
API函数 | 说明 |
---|---|
aio_read | 异步读操作 |
aio_write | 异步写操作 |
aio_error | 检查异步请求的状态 |
aio_return | 获得异步请求完成时的返回值 |
aio_suspend | 挂起调用进程,直到一个或多个异步请求已完成 |
aio_cancel | 取消异步请求 |
lio_list | 发起一系列异步I/O请求 |
上述API调用都会用到 struct aiocb 结构体:
struct aiocb {
int aio_fildes; //文件描述符
off_t aio_offset; //文件偏移量
volatile void *aio_buf; //缓冲区
size_t aio_nbytes; //数据长度
int aio_reqprio; //请求优先级
struct sigevent aio_sigevent; //通知方式
int aio_lio_opcode; //要执行的操作
};
编译时加参数 -lrt
aio_error
检查异步请求状态
int aio_error(const struct aiocb *aiocbp);
返回值 | 含义 |
---|---|
EINPROGRESS | 该请求尚未完成 |
ECANCELED | 该请求被撤销 |
0 | 请求成功完成 |
出错 | 错误信息存入errno中 |
aio_read 异步读请求
int aio_read(struct aiocb *aiocbp);
例子:读取test.txt 文件
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<errno.h>
#include<fcntl.h>
#include<aio.h>
#include<stdlib.h>
#include<strings.h>
#define BUFSIZE 256
int main()
{
struct aiocb cbp;
int fd,ret;
int i = 0;
fd = open("test.txt",O_RDONLY);
if(fd < 0)
{
perror("open error\n");
}
//填充struct aiocb 结构体
bzero(&cbp,sizeof(cbp));
//指定缓冲区
cbp.aio_buf = (volatile void*)malloc(BUFSIZE+1);
//请求读取的字节数
cbp.aio_nbytes = BUFSIZE;
//文件偏移
cbp.aio_offset = 0;
//读取的文件描述符
cbp.aio_fildes = fd;
//发起读请求
ret = aio_read(&cbp);
if(ret < 0)
{
perror("aio_read error\n");
exit(1);
}
//查看异步读取的状态,直到读取请求完成
for(i = 1;aio_error(&cbp) == EINPROGRESS;i++)
{
printf("No.%3d\n",i);
}
//读取返回值
ret = aio_return(&cbp);
printf("return %d\n",ret);
// sleep(1);
printf("%s\n",(char*)cbp.aio_buf);
close(fd);
return 0;
}
从上图看出,循环检查了3次异步读写的状态,指定的256字节才读取完毕,最后返回读取的字节数256。
如果注释掉异步读的状态检查:
...
//查看异步读取的状态,直到读取请求完成
/* for(i = 1;aio_error(&cbp) == EINPROGRESS;i++)
{
printf("No.%3d\n",i);
}
ret = aio_return(&cbp);
printf("return %d\n",ret);
*/
...
发现什么都没输出,这是因为程序结束的时候,异步读请求还没完成,所以buf缓冲区还没有读进去数据。
如果将上面代码中的 sleep 的注释去掉,让异步请求发起后,程序等待1秒后再输出,就会发现成功读取到了数据。
用GDB单步跟踪上面程序,当发起异步读请求时: