aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--man7/aio.7458
1 files changed, 458 insertions, 0 deletions
diff --git a/man7/aio.7 b/man7/aio.7
new file mode 100644
index 0000000000..09995bc77d
--- /dev/null
+++ b/man7/aio.7
@@ -0,0 +1,458 @@
+'\" t
+.\" Copyright (c) 2010 by Michael Kerrisk <mtk.manpages@gmail.com>
+.\"
+.\" Permission is granted to make and distribute verbatim copies of this
+.\" manual provided the copyright notice and this permission notice are
+.\" preserved on all copies.
+.\"
+.\" Permission is granted to copy and distribute modified versions of this
+.\" manual under the conditions for verbatim copying, provided that the
+.\" entire resulting derived work is distributed under the terms of a
+.\" permission notice identical to this one.
+.\"
+.\" Since the Linux kernel and libraries are constantly changing, this
+.\" manual page may be incorrect or out-of-date. The author(s) assume no
+.\" responsibility for errors or omissions, or for damages resulting from
+.\" the use of the information contained herein. The author(s) may not
+.\" have taken the same level of care in the production of this manual,
+.\" which is licensed free of charge, as they might when working
+.\" professionally.
+.\"
+.\" Formatted or processed versions of this manual, if unaccompanied by
+.\" the source, must acknowledge the copyright and authors of this work.
+.\"
+.TH AIO 7 2010-10-02 "Linux" "Linux Programmer's Manual"
+.SH NAME
+aio \- POSIX asynchronous I/O overview
+.SH DESCRIPTION
+The POSIX asynchronous I/O (AIO) interface allows applications
+to initiate one or more I/O operations that are performed
+asynchronously (i.e., in the background).
+The application can elect to be notified of completion of
+the I/O operation in a variety of ways:
+by delivery of a signal, by instantiation of a thread,
+or no notification at all.
+
+The POSIX AIO interface consists of the following functions:
+.TP 16
+.BR aio_read (3)
+Enqueue a read request.
+This is the asynchronous analog of
+.BR read (2).
+.TP
+.BR aio_write (3)
+Enqueue a write request.
+This is the asynchronous analog of
+.BR write (2).
+.TP
+.BR aio_fsync (3)
+Enqueue a sync request for the I/O operations on a file descriptor.
+This is the asynchronous analog of
+.BR fsync (2)
+and
+.BR fdatasync (2).
+.TP
+.BR aio_error (3)
+Obtain the error status of an enqueued I/O request.
+.TP
+.BR aio_return (3)
+Obtain the return status of a completed I/O request.
+.TP
+.BR aio_suspend (3)
+Suspend the caller until one or more of a specified set of
+I/O requests completes.
+.TP
+.BR aio_cancel (3)
+Attempt to cancel outstanding I/O requests on a specified
+file descriptor.
+.TP
+.BR lio_listio (3)
+Enqueue multiple I/O requests using a single function call.
+.PP
+The
+.I aiocb
+("asynchronous I/O control block") structure defines
+parameters that control an I/O operation.
+An argument of this type is employed with all of the functions listed above.
+This structure has the following form:
+.PP
+.in +4n
+.nf
+#include <aiocb.h>
+
+struct aiocb {
+ /* The order of these fields is implementation-dependent */
+
+ 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 */
+ struct sigevent aio_sigevent; /* Notification method */
+ int aio_lio_opcode; /* Operation to be performed;
+ lio_listio() only */
+
+ /* Various implementation-internal fields not shown */
+};
+
+/* Operation codes for 'aio_lio_opcode': */
+
+enum { LIO_READ, LIO_WRITE, LIO_NOP };
+
+.fi
+.in
+The fields of this structure are as follows:
+.TP 16
+.I aio_filedes
+The file descriptor on which the I/O operation is to be performed.
+.TP
+.I aio_offset
+This is the file offset at which the I/O operation is to be performed.
+.TP
+.I aio_buf
+This is the buffer used to transfer data for a read or write operation.
+.TP
+.I aio_nbytes
+This is the size of the buffer pointed to by
+.IR aio_buf .
+.TP
+.I aio_reqprio
+This field specifies a value that is subtracted
+from the calling thread's real-time priority in order to
+determine the priority for execution of this I/O request.
+.BR pthread_setschedparam (3)).
+The specified value must be between 0 and the value returned by
+.IR sysconf(_SC_AIO_PRIO_DELTA_MAX) .
+This field is ignored file synchronization operations.
+.TP
+.I aio_sigevent
+This field is a structure that specifies how the caller is
+to be notified when the asynchronous I/O operation completes.
+Possible values for
+.IR aio_sigevent.sigev_notify
+are
+.BR SIGEV_NONE ,
+.BR SIGEV_SIGNAL ,
+and
+.BR SIGEV_THREAD .
+See
+.BR sigevent (7)
+for further details.
+.TP
+.I aio_lio_opcode
+The type of operation to be performed; used only for
+.BR lio_listio (3).
+.PP
+In addition to the standard functions listed above,
+the GNU C library provides the following extension to the POSIX AIO API:
+.TP 16
+.BR aio_init (3)
+Set parameters for tuning the behavior of the glibc POSIX AIO implementation.
+.SH NOTES
+It is a good idea to zero out the control block buffer before use (see
+.BR memset (3)).
+The control block buffer and the buffer pointed to by
+.I aio_buf
+must not be changed while the I/O operation is in progress.
+These buffers must remain valid until the I/O operation completes.
+
+Simultaneous asynchronous read or write operations using the same
+.I aiocb
+structure yield undefined results.
+
+The current Linux POSIX AIO implementation is provided in userspace by glibc.
+This has a number of limitations, most notably that maintaining multiple
+threads to perform I/O operations is expensive and scales poorly.
+Work has been in progress for some time on a kernel
+state-machine-based implementation of asynchronous I/O
+(see
+.BR io_submit (2),
+.BR io_setup (2),
+.BR io_cancel (2),
+.BR io_destroy (2),
+.BR io_getevents (2)),
+but this implementation hasn't yet matured to the point where
+the POSIX AIO implementation can be completely
+reimplemented using the kernel system calls.
+.\" http://lse.sourceforge.net/io/aio.html
+.\" http://lse.sourceforge.net/io/aionotes.txt
+.\" http://lwn.net/Articles/148755/
+.SH ERRORS
+.TP
+.B EINVAL
+The
+.I aio_reqprio
+field of the
+.I aiocb
+structure was less than 0, or greater than the limit specified by
+.IR sysconf(_SC_AIO_PRIO_DELTA_MAX) .
+.SH VERSIONS
+The POSIX AIO interfaces are provided by glibc since version 2.1.
+.SH CONFORMING TO
+POSIX.1-2001, POSIX.1-2008
+.SH EXAMPLE
+The program below opens each of the files named in its command-line
+arguments and queues a request on the resulting file descriptor using
+.BR aio_read (3).
+The program then loops,
+periodically monitoring each of the I/O operations
+that is still in progress using
+.BR aio_error (3).
+Each of the I/O requests is set up to provide notification by delivery
+of a signal.
+After all I/O requests have completed,
+the program retrieves their status using
+.BR aio_return (3).
+
+The
+.B SIGQUIT
+signal (generated by typing control-\\) causes the program to request
+cancellation of each of the outstanding requests using
+.BR aio_cancel (3).
+
+Here is an example of what we might see when running this program.
+In this example, the program queues two requests to standard input,
+and these are satisfied by two lines of input containing
+"abc" and "x".
+
+.in +4n
+.nf
+$ \fB./a.out /dev/stdin /dev/stdin\fP
+opened /dev/stdin on descriptor 3
+opened /dev/stdin on descriptor 4
+aio_error():
+ for request 0 (descriptor 3): In progress
+ for request 1 (descriptor 4): In progress
+\fBabc\fP
+I/O completion signal received
+aio_error():
+ for request 0 (descriptor 3): I/O succeeded
+ for request 1 (descriptor 4): In progress
+aio_error():
+ for request 1 (descriptor 4): In progress
+\fBx\fP
+I/O completion signal received
+aio_error():
+ for request 1 (descriptor 4): I/O succeeded
+All I/O requests completed
+aio_return():
+ for request 0 (descriptor 3): 4
+ for request 1 (descriptor 4): 2
+.fi
+.in
+.SS Program source
+\&
+.nf
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <aio.h>
+#include <signal.h>
+
+#define BUF_SIZE 20 /* Size of buffers for read operations */
+
+#define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); } while (0)
+
+#define errMsg(msg) do { perror(msg); } while (0)
+
+struct ioRequest { /* Application\-defined structure for tracking
+ I/O requests */
+ int reqNum;
+ int status;
+ struct aiocb *aiocbp;
+};
+
+static volatile sig_atomic_t gotSIGQUIT = 0;
+ /* On delivery of SIGQUIT, we attempt to
+ cancel all outstanding I/O requests */
+
+static void /* Handler for SIGQUIT */
+quitHandler(int sig)
+{
+ gotSIGQUIT = 1;
+}
+
+#define IO_SIGNAL SIGUSR1 /* Signal used to notify I/O completion */
+
+static void /* Handler for I/O completion signal */
+aioSigHandler(int sig, siginfo_t *si, void *ucontext)
+{
+ write(STDOUT_FILENO, "I/O completion signal received\\n", 31);
+
+ /* The corresponding ioRequest structure would be available as
+ struct ioRequest *ioReq = si\->si_value.sival_ptr;
+ and the file descriptor would then be available via
+ ioReq\->aiocbp\->aio_fildes */
+}
+
+int
+main(int argc, char *argv[])
+{
+ struct ioRequest *ioList;
+ struct aiocb *aiocbList;
+ struct sigaction sa;
+ int s, j;
+ int numReqs; /* Total number of queued I/O requests */
+ int openReqs; /* Number of I/O requests still in progress */
+
+ if (argc < 2) {
+ fprintf(stderr, "Usage: %s <pathname> <pathname>...\\n",
+ argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ numReqs = argc \- 1;
+
+ /* Allocate our arrays */
+
+ ioList = calloc(numReqs, sizeof(struct ioRequest));
+ if (ioList == NULL)
+ errExit("calloc");
+
+ aiocbList = calloc(numReqs, sizeof(struct aiocb));
+ if (aiocbList == NULL)
+ errExit("calloc");
+
+ /* Establish handlers for SIGQUIT and the I/O completion signal */
+
+ sa.sa_flags = SA_RESTART;
+ sigemptyset(&sa.sa_mask);
+
+ sa.sa_handler = quitHandler;
+ if (sigaction(SIGQUIT, &sa, NULL) == \-1)
+ errExit("sigaction");
+
+ sa.sa_flags = SA_RESTART | SA_SIGINFO;
+ sa.sa_sigaction = aioSigHandler;
+ if (sigaction(IO_SIGNAL, &sa, NULL) == \-1)
+ errExit("sigaction");
+
+ /* Open each file specified on the command line, and queue
+ a read request on the resulting file descriptor */
+
+ for (j = 0; j < numReqs; j++) {
+ ioList[j].reqNum = j;
+ ioList[j].status = EINPROGRESS;
+ ioList[j].aiocbp = &aiocbList[j];
+
+ ioList[j].aiocbp\->aio_fildes = open(argv[j + 1], O_RDONLY);
+ if (ioList[j].aiocbp\->aio_fildes == \-1)
+ errExit("open");
+ printf("opened %s on descriptor %d\\n", argv[j + 1],
+ ioList[j].aiocbp\->aio_fildes);
+
+ ioList[j].aiocbp\->aio_buf = malloc(BUF_SIZE);
+ if (ioList[j].aiocbp\->aio_buf == NULL)
+ errExit("malloc");
+
+ ioList[j].aiocbp\->aio_nbytes = BUF_SIZE;
+ ioList[j].aiocbp\->aio_reqprio = 0;
+ ioList[j].aiocbp\->aio_offset = 0;
+ ioList[j].aiocbp\->aio_sigevent.sigev_notify = SIGEV_SIGNAL;
+ ioList[j].aiocbp\->aio_sigevent.sigev_signo = IO_SIGNAL;
+ ioList[j].aiocbp\->aio_sigevent.sigev_value.sival_ptr =
+ &ioList[j];
+
+ s = aio_read(ioList[j].aiocbp);
+ if (s == \-1)
+ errExit("aio_read");
+ }
+
+ openReqs = numReqs;
+
+ /* Loop, monitoring status of I/O requests */
+
+ while (openReqs > 0) {
+ sleep(3); /* Delay between each monitoring step */
+
+ if (gotSIGQUIT) {
+
+ /* On receipt of SIGQUIT, attempt to cancel each of the
+ outstanding I/O requests, and display status returned
+ from the cancellation requests */
+
+ printf("got SIGQUIT; canceling I/O requests: \\n");
+
+ for (j = 0; j < numReqs; j++) {
+ if (ioList[j].status == EINPROGRESS) {
+ printf(" Request %d on descriptor %d:", j,
+ ioList[j].aiocbp\->aio_fildes);
+ s = aio_cancel(ioList[j].aiocbp\->aio_fildes,
+ ioList[j].aiocbp);
+ if (s == AIO_CANCELED)
+ printf("I/O canceled\\n");
+ else if (s == AIO_NOTCANCELED)
+ printf("I/O not canceled\\n");
+ else if (s == AIO_ALLDONE)
+ printf("I/O all done\\n");
+ else
+ errMsg("aio_cancel");
+ }
+ }
+
+ gotSIGQUIT = 0;
+ }
+
+ /* Check the status of each I/O request that is still
+ in progress */
+
+ printf("aio_error():\\n");
+ for (j = 0; j < numReqs; j++) {
+ if (ioList[j].status == EINPROGRESS) {
+ printf(" for request %d (descriptor %d): ",
+ j, ioList[j].aiocbp\->aio_fildes);
+ ioList[j].status = aio_error(ioList[j].aiocbp);
+
+ switch (ioList[j].status) {
+ case 0:
+ printf("I/O succeeded\\n");
+ break;
+ case EINPROGRESS:
+ printf("In progress\\n");
+ break;
+ case ECANCELED:
+ printf("Canceled\\n");
+ break;
+ default:
+ errMsg("aio_error");
+ break;
+ }
+
+ if (ioList[j].status != EINPROGRESS)
+ openReqs\-\-;
+ }
+ }
+ }
+
+ printf("All I/O requests completed\\n");
+
+ /* Check status return of all I/O requests */
+
+ printf("aio_return():\\n");
+ for (j = 0; j < numReqs; j++) {
+ ssize_t s;
+
+ s = aio_return(ioList[j].aiocbp);
+ printf(" for request %d (descriptor %d): %ld\\n",
+ j, ioList[j].aiocbp\->aio_fildes, (long) s);
+ }
+
+ exit(EXIT_SUCCESS);
+}
+.fi
+.SH SEE ALSO
+.ad l
+.BR io_submit (2),
+.BR io_setup (2),
+.BR io_cancel (2),
+.BR io_destroy (2),
+.BR io_getevents (2)),
+.BR aio_cancel (3),
+.BR aio_error (3),
+.BR aio_init (3),
+.BR aio_read (3),
+.BR aio_return (3),
+.BR aio_write (3),
+.BR lio_listio (3),
+http://www.squid-cache.org/~adrian/Reprint-Pulavarty-OLS2003.pdf