什么是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);
}