什么是aio:异步io,让io过程异步进行,从而提升读写效率
涉及状态切换:用户态、内核态
如何进行aio读操作:
执行异步操作的时候,函数直接返回(可以先去做其他事情)
同时调用内核中对应的系统函数
内核中函数执行对应io功能,执行完毕之后把数据放到执行的缓冲区中
之后用户态可以去检查缓冲区是否有数据,或者用信号方式获取数据
aio编程模型:Include: <aio.h>. Link with -lrt.
1.准备缓冲区
struct aiocb {
int aio_fildes; /* File descriptor */
off_t aio_offset; /* File offset */
volatile void *aio_buf; /* Location of buffer */
size_t aio_nbytes; /* Length of transfer */
int aio_reqprio; /* Request priority offset */
struct sigevent aio_sigevent; /* Signal number and value */
int aio_lio_opcode;/* Operation to be performed */
};
2.异步操作
int aio_write(struct aiocb *aiocbp);
int aio_read(struct aiocb *aiocbp);
3.检查是否操作完毕
aio_error 用轮询的方式不断检查操作是否完毕
aio_suspend 阻塞式等待某个io操作完成,但是只要有一个操作完成了它就会返回
lio_listio 阻塞式等待,第一个参数设置为LIO_WAIT,可以等所有操作都完成再返回
中断机制,事件机制:第一个参数设置为LIO_NOWIAT
4.得到数据
aio_return
5.收尾
io多路复用和aio的区别:
io多路复用没有状态切换,aio有,要切换到内核态
// 异步读
void _aio_read()
{
// 1.准备缓冲区
struct aiocb cb = {0};
int fd = open("1.txt", O_RDONLY);
if (-1 == fd)
{
printf("打开文件失败%m\n");
return;
}
printf("打开文件成功\n");
cb.aio_fildes = fd; // 绑定文件描述符号
cb.aio_buf = calloc(1024, sizeof(int)); // 开辟缓冲区
cb.aio_nbytes = 1023; // 要收的字节数
// 2.异步操作(读)
int r = aio_read(&cb);
if (-1 == r)
{
printf("读取文件失败%m\n");
return;
}
printf("读取文件成功\n");
// 3.检查是否操作完毕
// while (aio_error(&cb))
// ;
// 用另一种方式
struct aiocb *cb_list[2] = {0};
cb_list[0] = &cb;
// 里面可以放多个cb,比如把写也放进来
r = aio_suspend(cb_list, 2, NULL); // 但是只要有一个结束了,它就返回了
if (-1 == r)
{
printf("aio_suspend失败%m\n");
return;
}
printf("aio_suspend结束\n");
// 4.得到数据
r = aio_return(&cb);
if (r > 0)
{
printf("读到了%d字节数据:%s\n", r, cb.aio_buf);
}
// 5.收尾
free(cb.aio_buf);
close(fd);
}
// 异步写
void _aio_write()
{
// 1.准备缓冲区
struct aiocb cb = {0};
int fd = open("2.txt", O_WRONLY | O_APPEND);
if (-1 == fd)
{
printf("打开文件失败%m\n");
return;
}
printf("打开文件成功\n");
cb.aio_fildes = fd; // 绑定文件描述符号
cb.aio_buf = calloc(1024, sizeof(int)); // 开辟缓冲区
strcpy(cb.aio_buf, "aio追加写:hello world\n"); // 将要写入的数据放入缓冲区
cb.aio_nbytes = strlen(cb.aio_buf); // 要写的字节数
// 2.异步操作(写)
int r = aio_write(&cb);
if (-1 == r)
{
printf("写文件失败%m\n");
return;
}
printf("写文件成功\n");
// 3.检查是否操作完毕
while (aio_error(&cb))
;
// 4.得到数据
r = aio_return(&cb);
if (r > 0)
{
printf("写入了%d字节数据\n", r);
}
// 5.收尾
free(cb.aio_buf);
close(fd);
}