NAME
aio
—
asynchronous I/O (REALTIME)
LIBRARY
library “librt”
SYNOPSIS
#include
<aio.h>
DESCRIPTION
The IEEE Std 1003.1-2001 (“POSIX.1”) standard defines an interface for asynchronous input and output. Although in NetBSD this is provided as part of the library “librt”, the implementation largely resides in the kernel.Rationale
The rationale can be roughly summarized with the following points.
- To increase performance by providing a mechanism to carry out I/O without blocking. Theoretically, if I/O would never block, neither at the software nor at the hardware level, the overhead of I/O would become zero, and processes would no longer be I/O bound.
- To segregate the different I/O operations into logically distinctive
procedures. Unlike with the standard
stdio(3), the
aio
interface separates queuing and submitting I/O operations to the kernel, and receiving notifications of operation completion from the kernel. - To provide an uniform and standardized framework for asynchronous I/O. For
instance,
aio
avoids the need for (and the overhead of) extra worker threads sometimes used to perform asynchronous I/O.
Asynchronous I/O Control Block
The Asynchronous I/O Control Block is the basic operational unit
behind aio
. This is required since an arbitrary
number of operations can be started at once, and because each operation can
be either input or output. This block is represented by the
aiocb
structure, which is defined in the
<aio.h>
header. The
following fields are available for user applications:
off_t aio_offset; void *aio_buf; size_t aio_nbytes; int aio_fildes; int aio_lio_opcode; int aio_reqprio; struct sigevent aio_sigevent;
The fields are:
- The aio_offset specifies the implicit file offset at which the I/O operations are performed. This cannot be expected to be the actual read/write offset of the file descriptor.
- The aio_buf member is a pointer to the buffer to which data is going to be written or to which the read operation stores data.
- The aio_nbytes specifies the length of aio_buf.
- The aio_fildes specifies the used file descriptor.
- The aio_lio_opcode is used by the
lio_listio
() function to initialize a list of I/O requests with a single call. - The aio_reqprio member can be used to lower the
scheduling priority of an
aio
operation. This is only available if_POSIX_PRIORITIZED_IO
and_POSIX_PRIORITY_SCHEDULING
are defined, and the associated file descriptor supports it. - The aio_sigevent member is used to specify how the
calling process is notified once an
aio
operation completes.
The members aio_buf,
aio_fildes, and aio_nbytes are
conceptually similar to the parameters ‘buf’,
‘fildes’, and ‘nbytes’ used in the standard
read(2) and
write(2) functions. For example, the caller can read
aio_nbytes from a file associated with the file
descriptor aio_fildes into the buffer
aio_buf. All appropriate fields should be initialized
by the caller before
aio_read
()
or
aio_write
()
is called.
File Offsets
Asynchronous I/O operations are not strictly sequential;
operations are carried out in arbitrary order and more than one operation
for one file descriptor can be started. The requested read or write
operation starts from the absolute position specified by
aio_offset, as if
lseek(2) would have been called with SEEK_SET
immediately prior to the operation. The POSIX standard does not specify what
happens after an aio
operation has been successfully
completed. Depending on the implementation, the actual file offset may or
may not be updated.
Errors and Completion
Asynchronous I/O operations are said to be complete when:
- An error is detected.
- The I/O transfer is performed successfully.
- The operation is canceled.
If an error condition is detected that prevents an
operation from being started, the request is not enqueued. In this case the
read and write functions,
aio_read
()
and
aio_write
(),
return immediately, setting the global errno to
indicate the cause of the error.
After an operation has been successfully enqueued,
aio_error
()
and
aio_return
()
must be used to determine the status of the operation and to determine any
error conditions. This includes the conditions reported by the standard
read(2), write(2), and
fsync(2). The request remains enqueued and consumes process and
system resources until aio_return
() is called.
Waiting for Completion
The aio
interface supports both polling
and notification models. The first can be implemented by simply repeatedly
calling the aio_error
() function to test the status
of an operation. Once the operation has completed,
aio_return
() is used to free the
aiocb structure for re-use.
The notification model is implemented by using the aio_sigevent member of the Asynchronous I/O Control Block. The operational model and the used structure are described in sigevent(3).
The
aio_suspend
()
function can be used to wait for the completion of one or more operations.
It is possible to set a timeout so that the process can continue the
execution and take recovery actions if the aio
operations do not complete as expected.
Cancellation and Synchronization
The
aio_cancel
()
function can be used to request cancellation of an asynchronous I/O
operation. Note however that not all of them can be canceled. The same
aiocb used to start the operation may be used as a
handle for identification. It is also possible to request cancellation of
all operations pending for a file.
Comparable to
fsync(2), the
aio_fsync
()
function can be used to synchronize the contents of permanent storage when
multiple asynchronous I/O operations are outstanding for the file or device.
The synchronization operation includes only those requests that have already
been successfully enqueued.
FUNCTIONS
The following functions comprise the API of the
aio
interface:
Function | Description |
aio_cancel(3) | cancel an outstanding asynchronous I/O operation |
aio_error(3) | retrieve error status of asynchronous I/O operation |
aio_fsync(3) | asynchronous data synchronization of file |
aio_read(3) | asynchronous read from a file |
aio_return(3) | get return status of asynchronous I/O operation |
aio_suspend(3) | suspend until operations or timeout complete |
aio_write(3) | asynchronous write to a file |
lio_listio(3) | list directed I/O |
COMPATIBILITY
Unfortunately, the POSIX asynchronous I/O implementations vary
slightly. Some implementations provide a slightly different API with
possible extensions. For instance, the FreeBSD
implementation uses a function
‘aio_waitcomplete
()’ to wait for the
next completion of an aio
request.
STANDARDS
The aio
interface is expected to conform
to the IEEE Std 1003.1-2001
(“POSIX.1”) standard.
HISTORY
The aio
interface first appeared in
NetBSD 5.0.
CAVEATS
Few limitations can be mentioned:
- Undefined behavior results if simultaneous asynchronous operations use the same Asynchronous I/O Control Block.
- When an asynchronous read operation is outstanding, undefined behavior may follow if the contents of aiocb are altered, or if memory associated with the structure, or the aio_buf buffer, is deallocated.