什么是AIO?
AIO就是允许应用程序启动一个或多个异步执行的I / O操作。
AIO的思想:进程发起I/O操作,而不用阻塞或等待任何操作完成,稍后或在接收到I/O操作完成通知时,进程可以I/O操作结果。
也就是说,你可以在进程读写文件的同时,干你自己相干的事,而不用等待进程读写数据,节省时间。
AIO的结构体:
struct aiocb {
int aio_fildes; /* 要被读写的文件描述符 */
off_t aio_offset; /* 文件偏移量*/
volatile void *aio_buf; /*读写对应的buf */
size_t aio_nbytes; /* 读写字节数 */
int aio_reqprio; /* 优先级 */
struct sigevent aio_sigevent; /* 通知方法 */
};
其中通知方法一共有三种:
1.通过信号
2.通过启动一个线程
3.不作通知
struct sigevent {
int sigev_notify; /* 通知方法 */
int sigev_signo; /* 通知信号 */
union sigval sigev_value; /* 传递的数据*/
void (*sigev_notify_function) (union sigval);/* 用线程的函数 */
void *sigev_notify_attributes;/* 通知线程的属性
};
AIO接口 API
aio_read 异步读
aio_write 异步写
aio_error 检查异步请求状态
aio_return 获得异步返回状态
aio_suspend 挂起调用进程,直到一个或多个异步请求已经完成(或失败)
aio_cancel 取消异步I/O请求
lio_listio 发起大量I/O操作请求
int aio_read(struct aiocb *aiocbp);
这个函数就是异步读取一个描述符
#include <iostream>
#include <aio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
using namespace std;
//当操作完成时,会发送信号,然后会执行这个函数
void p(int t,siginfo_t *q,void *r)
{
char *c = (char *)q->si_ptr;
cout << c << endl;
cout << "读取完成" << endl;
}
int main()
{
//注册信号
struct sigaction act;
memset(&act,0,sizeof(act));
act.sa_sigaction = p;
act.sa_flags = SA_SIGINFO | SA_RESTART;
sigaction(SIGRTMIN,&act,NULL);
//int aio_read(struct aiocb *aiocbp);
struct aiocb aios;
memset(&aios,0,sizeof(aios));
aios.aio_fildes = open("www.txt",O_RDONLY);
if(aios.aio_fildes < 0)
{
perror("open err:");
return -1;
}
aios.aio_offset = 0;
//这个是写入的buf
char c[100] = { 0 };
aios.aio_buf = (void *)c;
aios.aio_nbytes = 100;
//这是说,执行完成后发送信号
aios.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
//这个是发送的信号,我使用kill -l随机取了一个
aios.aio_sigevent.sigev_signo = SIGRTMIN;
//这个是发送的值(得了解可靠信号和不可靠信号的知识)
aios.aio_sigevent.sigev_value.sival_ptr = (void *)c;
if(aio_read(&aios) < 0)
{
perror("aid_read err:");
return -1;
}
cout << "看看谁先执行" << endl;
sleep(10);
cout << "Hello world" << endl;
return 0;
}
注:如果编译时出现错误undefined reference to 'aio_read',那么,很可能是编译时POSIX实时扩展库librt的链接。
在编译时候后面加上 -lrt
不用信号和线程的情况:
//不用信号,只能执行完其他操作后查看状态
while(1)
{
int t = aio_error(aios);
int flag = 0;
switch(t)
{
case EINPROGRESS:
cout << "请求尚未完成" << endl;
break;
case ECANCELED:
cout << "请求取消了" << endl;
break;
case -1:
perror("aio err:");
return;
case 0:
cout << "请求成功" << endl;
flag = 1;
break;
}
if(flag)
break;
}
还有就是这个函数,可以 发起大量I/O操作请求
int lio_listio(int mode, struct aiocb *const aiocb_list[],int nitems, struct sigevent *sevp);
其他函数看man手册就可以了