简介:Linux 异步 I/O 是 Linux 内核中提供的一个相当新的增强。它是 2.6 版本内核的一个标准特性,但是我们在 2.4 版本内核的补丁中也可以找到它。AIO 背后的基本思想是允许进程发起很多 I/O 操作,而不用阻塞或等待任何操作完成。
异步非阻塞 I/O 模型是一种处理与 I/O 重叠进行的模型。读请求会立即返回,说明
read
请求已经成功发起了。在后台完成读操作时,应用程序然后会执行其他处理操作。当 read
的响应到达时,就会产生一个信号或执行一个基于线程的回调函数来完成这次 I/O 处理过程。
在一个进程中为了执行多个 I/O 请求而对计算操作和 I/O 处理进行重叠处理的能力利用了处理速度与 I/O 速度之间的差异。当一个或多个 I/O 请求挂起时,CPU 可以执行其他任务;或者更为常见的是,在发起其他 I/O 的同时对已经完成的 I/O 进行操作。
在异步非阻塞 I/O 中,我们可以同时发起多个传输操作。这需要每个传输操作都有惟一的上下文,这样我们才能在它们完成时区分到底是哪个传输操作完成了。在 AIO 中,这是一个
aiocb
(AIO I/O Control Block)结构。这个结构包含了有关传输的所有信息,包括为数据准备的用户缓冲区。在产生 I/O (称为完成)通知时,aiocb
结构就被用来惟一标识所完成的 I/O 操作。这个 API 的展示显示了如何使用它。
表 1. AIO 接口 API
aio_read |
请求异步读操作 |
aio_error |
检查异步请求的状态 |
aio_return |
获得完成的异步请求的返回状态 |
aio_write |
请求异步写操作 |
aio_suspend |
挂起调用进程,直到一个或多个异步请求已经完成(或失败) |
aio_cancel |
取消异步 I/O 请求 |
lio_listio |
发起一系列 I/O 操作 |
详细见:http://www.ibm.com/developerworks/cn/linux/l-async/
阻塞模式下的IO过程如下:
int fd = open(const char *pathname, int flags, mode_t mode); ssize_t pread(int fd, void *buf, size_t count, off_t offset); ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset); int close(int fd);
因为整个过程会等待read/write的返回,所以不需要任何额外的数据结构。但异步IO的思想是:应用程序不能阻塞在昂贵的系统调用上让CPU睡大觉,而是将IO操作抽象成一个个的任务单元提交给内核,内核完成IO任务后将结果放在应用程序可以取到的地方。这样在底层做I/O的这段时间内,CPU可以去干其他的计算任务。但异步的IO任务批量的提交和完成,必须有自身可描述的结构,最重要的两个就是iocb和io_event。
libaio中的structs struct iocb { void *data; /* Return in the io completion event */ unsigned key; /*r use in identifying io requests */ short aio_lio_opcode; short aio_reqprio; int aio_fildes; union { struct io_iocb_common c; struct io_iocb_vector v; struct io_iocb_poll poll; struct io_iocb_sockaddr saddr; } u; }; struct io_iocb_common { void *buf; unsigned long nbytes; long long offset; unsigned flags; unsigned resfd; };iocb是提交IO任务时用到的,可以完整地描述一个IO请求:
data是留给用来自定义的指针:可以设置为IO完成后的callback函数;
aio_lio_opcode表示操作的类型:IO_CMD_PWRITE | IO_CMD_PREAD;
aio_fildes是要操作的文件:fd;
io_iocb_common中的buf, nbytes, offset分别记录的IO请求的mem buffer,大小和偏移。
struct io_event { void *data; struct iocb *obj; unsigned long res; unsigned long res2; };io_event是用来描述返回结果的:
obj就是之前提交IO任务时的iocb;
res和res2来表示IO任务完成的状态。
AIO实现一般使用libaio进行在用户层实现,libaio提供了很多简易的操作API:
libaio提供的API有:io_setup, io_submit, io_getevents, io_destroy。
1. 建立IO任务
int io_setup (int maxevents, io_context_t *ctxp);
io_context_t对应内核中一个结构,为异步IO请求提供上下文环境。注意在setup前必须将io_context_t初始化为0。当然,这里也需要open需要操作的文件,注意设置O_DIRECT标志。
2.提交IO任务
long io_submit (aio_context_t ctx_id, long nr, struct iocb **iocbpp);
提交任务之前必须先填充iocb结构体,libaio提供的包装函数说明了需要完成的工作:
void io_prep_pread(struct iocb *iocb, int fd, void *buf, size_t count, long long offset) { memset(iocb, 0, sizeof(*iocb)); iocb->aio_fildes = fd; iocb->aio_lio_opcode = IO_CMD_PREAD; iocb->aio_reqprio = 0; iocb->u.c.buf = buf; iocb->u.c.nbytes = count; iocb->u.c.offset = offset; } void io_prep_pwrite(struct iocb *iocb, int fd, void *buf, size_t count, long long offset) { memset(iocb, 0, sizeof(*iocb)); iocb->aio_fildes = fd; iocb->aio_lio_opcode = IO_CMD_PWRITE; iocb->aio_reqprio = 0; iocb->u.c.buf = buf; iocb->u.c.nbytes = count; iocb->u.c.offset = offset; }这里注意读写的buf都必须是按扇区对齐的,可以用posix_memalign来分配。
3.获取完成的IO
long io_getevents (aio_context_t ctx_id, long min_nr, long nr, struct io_event *events, struct timespec *timeout);
这里最重要的就是提供一个io_event数组给内核来copy完成的IO请求到这里,数组的大小是io_setup时指定的maxevents。
timeout是指等待IO完成的超时时间,设置为NULL表示一直等待所有到IO的完成。
4.销毁IO任务
int io_destroy (io_context_t ctx);
相关推荐
在Linux操作系统中,异步I/O(Asynchronous Input/Output,简称AIO)是一种提高程序效率的方法,它允许程序在不等待I/O操作完成的情况下继续执行其他任务。本压缩包"linux_aio.zip"包含了关于如何在Linux下开启AIO...
注意,Linux AIO现在包含在io_uring API中( , )。 以下说明对旧内核最为有用。介绍异步输入/输出(AIO)接口允许并行提交许多I / O请求,而每个请求没有线程的开销。 本文档的目的是解释如何使用Linux AIO接口,...
### Linux异步IO aio #### 引言 随着网络技术的发展和CPU性能的提升,传统的网络编程接口(如Unix套接字API)已逐渐无法满足高效处理大量数据的需求。当前的操作系统在网络接口方面存在局限性,尤其是在数据传输...
总结起来,Linux的Socket I/O模型各有优劣,同步阻塞模型简单易用,但效率较低;同步非阻塞和I/O复用模型提高了效率,但需要处理复杂的回调逻辑;信号驱动I/O模型减少了轮询,但依赖于信号机制;异步I/O模型提供了...
在Linux操作系统中,有五种主要的IO模型,分别是阻塞IO、非阻塞IO、IO多路复用、信号驱动IO和异步IO。这些模型决定了应用程序如何与硬件进行交互,以获取和处理输入/输出数据。以下是对这五种模型的详细解释: 1. ...
本主题将深入探讨几种主要的网络I/O模型,包括阻塞I/O、非阻塞I/O、I/O复用、信号驱动I/O以及异步I/O,并结合Linux内核机制进行详细分析。 1. **阻塞I/O模型** 在阻塞I/O模型中,当进程尝试读取或写入数据时,如果...
《Linux设备驱动开发详解》这本书由宋宝华编写,详细阐述了Linux设备驱动的各个方面,包括I/O模型的选择和实现,是学习Linux驱动开发的宝贵参考资料。通过阅读本书,读者可以深入理解Linux内核的I/O机制,并掌握编写...
Linux内核支持AIO(异步I/O)接口,用于非阻塞的数据传输。 9. 虚拟化:KVM(Kernel-based Virtual Machine)是Linux内核内置的虚拟化技术,它允许在一个物理系统上运行多个虚拟机,每个虚拟机都有自己的操作系统...
总结起来,POSIX AIO API是Linux中提升应用程序性能的重要工具,它通过异步非阻塞的方式处理I/O操作,实现了I/O操作与计算任务的并行处理,降低了延迟,提升了系统效率。理解和熟练运用AIO,可以为高性能和高并发的...
根据UNIX网络编程的分类,Linux提供了五种I/O模型,分别是阻塞I/O、非阻塞I/O、I/O复用模型、信号驱动I/O以及异步I/O。 1. **阻塞I/O模型**: 在这个模型中,进程调用如`recvfrom`这样的系统调用时,会一直等待...
在Linux环境下,网络I/O(Input/Output)模型是系统进行网络通信的重要组成部分,它涉及到如何高效地处理来自网络的数据传输。本资源主要探讨的是在Linux操作系统中的网络I/O模型,包括其工作原理、常见类型以及优化...
本篇文章将深入探讨四种主要的IO模型:阻塞IO、无阻塞IO、多路复用IO(也称为选择器或I/O多路复用)以及异步IO,结合源码分析来帮助理解它们的工作原理和应用。 首先,我们来看**阻塞IO**。在这种模型中,当一个...
在Linux环境中,有三种主要的并发服务器模型:简单阻塞I/O(BIO)、多路复用I/O(如epoll)以及异步非阻塞I/O(AIO)。下面将详细介绍这三种模型,并探讨它们的优缺点和适用场景。 1. **简单阻塞I/O (BIO)** BIO是...
传统上,Linux采用的最常见I/O模型是同步I/O,其中应用程序在发出请求后会阻塞,直至请求完成。然而,随着现代应用程序对性能和效率需求的提升,异步I/O作为一种先进的技术,为解决高并发场景下的I/O瓶颈提供了新...
- **示例**: 例如,在Linux中,可以通过 `aio_read` 和 `aio_write` 函数实现异步I/O。 #### Nginx中的epoll, poll, select **select**, **poll**, 和 **epoll** 都属于I/O复用模型,用于同时监控多个文件描述符的...
在Linux中,有五种主要的I/O模型:同步阻塞I/O、同步非阻塞I/O、I/O多路复用(如select、poll和epoll)、信号驱动I/O以及异步I/O(AIO)。这些模型各自有不同的性能特性和应用场景,选择合适的I/O模型对于优化程序...
在Linux操作系统中,非阻塞I/O(Non-blocking I/O)是一种重要的编程模型,它用于处理高并发和低延迟的场景。与传统的阻塞I/O不同,非阻塞I/O在进行读写操作时,如果数据尚未准备好,不会挂起进程,而是立即返回一个...
在Linux中,I/O模型主要有五种:同步I/O、异步I/O、阻塞I/O、非阻塞I/O和I/O复用。其中,阻塞I/O是最常见的模型,当进行读写操作时,如果数据未准备好,进程会被挂起,直到数据准备完成。非阻塞I/O则允许进程在数据...