2024年5月6日发(作者:)

Linux® 中最常用的输入/输出(I/O)模型是同步 I/O。在这个模型中,当

请求发出之后,应用程序就会阻塞,直到请求满足为止。这是很好的一种解

决方案,因为调用应用程序在等待 I/O 请求完成时不需要使用任何中央处

理单元(CPU)。但是在某些情况中,I/O 请求可能需要与其他进程产生交叠。

可移植操作系统接口(POSIX)异步 I/O(AIO)应用程序接口(API)就提

供了这种功能。在本文中,我们将对这个 API 概要进行介绍,并来了解一

下如何使用它。

AIO 简介

Linux 异步 I/O 是 Linux 内核中提供的一个相当新的增强。它是 2.6 版本内核的一

个标准特性,但是我们在 2.4 版本内核的补丁中也可以找到它。AIO 背后的基本思想是允

许进程发起很多 I/O 操作,而不用阻塞或等待任何操作完成。稍后或在接收到 I/O 操作完

成的通知时,进程就可以检索 I/O 操作的结果。

Linux 上的 AIO 简介

本节将探索 Linux 的异步 I/O 模型,从而帮助我们理解如何在应用程序中使用这种技

术。

在传统的 I/O 模型中,有一个使用惟一句柄标识的 I/O 通道。在 UNIX® 中,这些句

柄是文件描述符(这对等同于文件、管道、套接字等等)。在阻塞 I/O 中,我们发起了一

次传输操作,当传输操作完成或发生错误时,系统调用

就会返回。

Linux 上的 AIO

在异步非阻塞 I/O 中,我们可以同时发起多个传

输操作。这需要每个传输操作都有惟一的上下文,这样

我们才能在它们完成时区分到底是哪个传输操作完成

了。在 AIO 中,这是一个

aiocb

(AIO I/O Control

AIO 在 2.5 版本的内核中首次出现,

现在已经是 2.6 版本的产品内核的一

个标准特性了。

Block)结构。这个结构包含了有关传输的所有信息,包括为数据准备的用户缓冲区。在产

生 I/O (称为完成)通知时,

aiocb

结构就被用来惟一标识所完成的 I/O 操作。这个 API

的展示显示了如何使用它。

AIO API

AIO 接口的 API 非常简单,但是它为数据传输提供了必需的功能,并给出了两个不同的

通知模型。表 1 给出了 AIO 的接口函数,本节稍后会更详细进行介绍。

表 1. AIO 接口 API

API 函数 说明

请求异步读操作

检查异步请求的状态

获得完成的异步请求的返回状态

请求异步写操作

挂起调用进程,直到一个或多个异步请求已经完成(或失败)

取消异步 I/O 请求

发起一系列 I/O 操作

aio_read

aio_error

aio_return

aio_write

aio_suspend

aio_cancel

lio_listio

每个 API 函数都使用

aiocb

结构开始或检查。这个结构有很多元素,但是清单 1 仅

仅给出了需要(或可以)使用的元素。清单 1. aiocb 结构中相关的域

struct aiocb {

int aio_fildes; // File Descriptor

int aio_lio_opcode; // Valid only for lio_listio

(r/w/nop)

volatile void *aio_buf; // Data Buffer

size_t aio_nbytes; // Number of Bytes in Data Buffer

struct sigevent aio_sigevent; // Notification Structure

/* Internal fields */

...

};

sigevent

结构告诉 AIO 在 I/O 操作完成时应该执行什么操作。我们将在 AIO 的展示

中对这个结构进行探索。现在我们将展示各个 AIO 的 API 函数是如何工作的,以及我们应

该如何使用它们。