编程接口指南

高性能 I/O

本节介绍实时进程的 I/O。在 SunOS 中,库提供了两组接口和调用来执行快速异步 I/O 操作。POSIX 异步 I/O 接口是最新标准。SunOS 环境还提供了文件和内存中同步操作和模式,以防止信息丢失和数据不一致。

标准 UNIX I/O 与应用程序程序员保持同步。调用 read(2)write(2) 的应用程序通常会等待系统调用完成为止。

实时应用程序需要有限的异步 I/O 行为。发出异步 I/O 调用的进程可继续执行而无需等待 I/O 操作完成。I/O 操作完成后会通知调用方。

异步 I/O 可用于任何 SunOS 文件。文件会同步打开并且不需要进行特殊标记。异步 I/O 传输包含三个元素:调用、请求和操作。应用程序调用异步 I/O 接口,将对 I/O 的请求放入队列中,然后立即返回调用。有时,系统会取消请求排队并启动 I/O 操作。

可以在任何文件描述符中混合异步和标准的 I/O 请求。系统不会维护任何特殊的读写请求序列,并且会对所有暂挂读写请求进行任意重新排序。如果应用程序需要特定序列,则应用程序必须确保在完成先前的操作之后再发出相关请求。

POSIX 异步 I/O

POSIX 异步 I/O 使用 aiocb 结构来执行。aiocb 控制块可标识每个异步 I/O 请求并包含所有控制信息。一个控制块每次只能用于一个请求。控制块可以在完成其请求之后重用。

典型的 POSIX 异步 I/O 操作是通过调用 aio_read(3RT)aio_write(3RT) 来启动的。可以使用轮询或信号来确定操作是否完成。如果使用信号确定操作是否完成,则可以唯一地标记每个操作。然后,在所生成信号的 si_value 组件中返回标记。请参见 siginfo(3HEAD) 手册页。

aio_read

aio_read(3RT) 是通过异步 I/O 控制块调用的,用于启动读操作。

aio_write

aio_write(3RT) 是通过异步 I/O 控制块调用的,用于启动写操作。

aio_return, aio_error

确定操作完成之后,分别调用 aio_return(3RT)aio_error(3RT) 可获取返回值和错误值。

aio_cancel

aio_cancel(3RT) 是通过异步 I/O 控制块调用的,用于取消暂挂操作。如果请求由控制块指定,则可以使用 aio_cancel 来取消特定请求。aio_cancel 还可以取消所有针对指定文件描述符暂挂的请求。

aio_fsync

aio_fsync(3RT) 用于对指定文件的所有暂挂 I/O 操作的异步 fsync(3C)fdatasync(3RT) 请求进行排队。

aio_suspend

aio_suspend(3RT) 用于暂停调用方,如同已将一个或多个先前的异步 I/O 请求同步。

Solaris 异步 I/O

本节介绍 Solaris 操作环境中的异步 I/O 操作。

通知 (SIGIO)

如果异步 I/O 调用成功返回,则表明 I/O 操作只是已排队并等待执行。实际操作包含一个返回值和一个潜在错误标识符。如果同步进行调用,则该返回值和潜在错误标识符会返回到调用方。完成 I/O 之后,会将返回值和错误值存储于用户在请求作为指向 aio_result_t 的指针时提供的位置。aio_result_t 的结构在 <sys/asynch.h> 中定义:

typedef struct aio_result_t {

 	ssize_t	aio_return; /* return value of read or write */

 	int 		aio_errno;  /* errno generated by the IO */

 } aio_result_t;

更新 aio_result_t 之后,便会将 SIGIO 信号传送到发出 I/O 请求的进程。

请注意,包含两个或多个暂挂的异步 I/O 操作的进程没有特定方法可确定 SIGIO 信号的成因。接收 SIGIO 的进程应该检查其所有可能会生成 SIGIO 信号的条件。

使用 aioread

aioread(3AIO) 例程是 read(2) 的异步版本。除了常规读取参数之外,aioread(3AIO) 还会采用可指定文件位置和 aio_result_t 结构地址的参数。有关操作的结果信息存储在 aio_result_t 结构中。文件位置指定操作之前要在文件内执行查找操作。无论 aioread(3AIO) 调用成功还是失败,都会更新文件指针。

使用 aiowrite

aiowrite(3AIO) 例程是 write(2) 的异步版本。除了常规写入参数之外,aiowrite(3AIO) 还会采用可指定文件位置和 aio_result_t 结构地址的参数。有关操作的结果信息存储在 aio_result_t 结构中。

文件位置指定操作之前要在文件内执行查找操作。如果 aiowrite(3AIO) 调用成功,则会将文件指针更新为指向可实现成功查找和写入的位置。如果写操作不再考虑后续的写入请求,则还会更新文件指针。

使用 aiocancel

aiocancel(3AIO) 例程可用于尝试取消 aio_result_t 结构指定作为参数的异步请求。仅当请求仍进行排队时,aiocancel(3AIO) 调用才会成功。如果操作正在进行中,则 aiocancel(3AIO) 会失败。

使用 aiowait

调用 aiowait(3AIO) 会阻塞调用过程,直到至少有一个未完成的异步 I/O 操作完成为止。超时参数是指等待 I/O 完成的最大时间间隔。超时值为 0 指明不需要等待。aiowait(3AIO) 会针对已完成的操作返回指向 aio_result_t 结构的指针。

使用 poll()

要以同步方式(而不是依赖于 SIGIO 中断)确定异步 I/O 事件是否完成,请使用 poll(2)。另外,还可以进行轮询来确定 SIGIO 中断的原因。

poll(2) 用于大量文件时会比较缓慢。此问题可通过 poll(7d) 进行解决。

使用 poll 驱动程序

使用 /dev/poll 可提供具有高度可伸缩性的轮询大量文件描述符的方法。这种可伸缩性是通过一组新的 API 和一个新驱动程序 /dev/poll 实现的。/dev/poll API 是 poll(2) 的备用项,而不是替换项。可以使用 poll(7d) 提供 /dev/poll API 的详细信息和示例。 如果正确使用,/dev/poll API 的扩展性将优于 poll(2)。此 API 尤其适用于满足以下条件的应用程序:

使用 close

文件通过调用 close(2) 来关闭。调用 close(2) 会取消任何可以关闭的未完成异步 I/O 请求。close(2) 将等待无法取消的操作。有关更多信息,请参见使用 aiocancelclose(2) 返回时,没有任何异步 I/O 针对文件描述符暂挂。文件关闭时,只取消排队到指定文件描述符的异步 I/O 请求,而不会取消针对其他文件描述符的任何 I/O 暂挂请求。

同步的 I/O

应用程序可能需要保证已将信息写入稳定存储器,或者保证按照特定顺序执行文件更新。为此,需要提供同步的 I/O。

同步模式

在 SunOS 中,如果系统确保以后每次打开文件之后均可以读取所有写入的数据,写操作即可成功。此检查假设物理存储介质不存在任何故障。如果物理存储介质上的数据映像可用于请求进程,则可成功传输读操作的数据。如果关联数据已成功传输或者 I/O 操作已诊断为不成功,则此操作便已完成。

当出现以下情况时,I/O 操作会实现同步的 I/O 数据完整性:

同步文件

fsync(3C)fdatasync(3RT) 将文件显式同步到辅助存储器中。

fsync(3C) 例程可保证在 I/O 文件完整性实现的级别同步接口。fdatasync(3RT) 可保证在 I/O 数据完整性实现的级别同步接口。

应用程序可以在每个 I/O 操作完成之前同步各操作。使用 open(2)fcntl(2) 针对文件描述设置 O_DSYNC 标志,可以确保所有 I/O 写入在操作完成之前便会完成 I/O 数据。针对文件描述设置 O_SYNC 标志,可以确保所有 I/O 写入在指示操作为完成之前便已完成。针对文件描述设置 O_RSYNC 标志,可以确保所有 I/O 读取(read(2)aio_read(3RT))都达到描述符设置所请求的相同完成级别。描述符设置可以为 O_DSYNCO_SYNC