]> git.ipfire.org Git - thirdparty/man-pages.git/blame - man7/aio.7
Many pages: Fix style issues reported by `make lint-groff`
[thirdparty/man-pages.git] / man7 / aio.7
CommitLineData
4076f289
MK
1.\" Copyright (c) 2010 by Michael Kerrisk <mtk.manpages@gmail.com>
2.\"
5fbde956 3.\" SPDX-License-Identifier: Linux-man-pages-copyleft
4076f289 4.\"
1d767b55 5.TH AIO 7 2021-03-22 "Linux" "Linux Programmer's Manual"
4076f289
MK
6.SH NAME
7aio \- POSIX asynchronous I/O overview
8.SH DESCRIPTION
9The POSIX asynchronous I/O (AIO) interface allows applications
10to initiate one or more I/O operations that are performed
11asynchronously (i.e., in the background).
12The application can elect to be notified of completion of
13the I/O operation in a variety of ways:
14by delivery of a signal, by instantiation of a thread,
15or no notification at all.
a721e8b2 16.PP
4076f289 17The POSIX AIO interface consists of the following functions:
0019177e 18.TP
4076f289
MK
19.BR aio_read (3)
20Enqueue a read request.
21This is the asynchronous analog of
22.BR read (2).
23.TP
24.BR aio_write (3)
25Enqueue a write request.
26This is the asynchronous analog of
27.BR write (2).
28.TP
29.BR aio_fsync (3)
30Enqueue a sync request for the I/O operations on a file descriptor.
31This is the asynchronous analog of
32.BR fsync (2)
33and
34.BR fdatasync (2).
35.TP
36.BR aio_error (3)
37Obtain the error status of an enqueued I/O request.
38.TP
39.BR aio_return (3)
40Obtain the return status of a completed I/O request.
41.TP
42.BR aio_suspend (3)
43Suspend the caller until one or more of a specified set of
44I/O requests completes.
45.TP
46.BR aio_cancel (3)
47Attempt to cancel outstanding I/O requests on a specified
48file descriptor.
49.TP
50.BR lio_listio (3)
51Enqueue multiple I/O requests using a single function call.
52.PP
53The
54.I aiocb
55("asynchronous I/O control block") structure defines
56parameters that control an I/O operation.
57An argument of this type is employed with all of the functions listed above.
58This structure has the following form:
59.PP
60.in +4n
b8302363 61.EX
4076f289
MK
62#include <aiocb.h>
63
64struct aiocb {
d064d41a 65 /* The order of these fields is implementation\-dependent */
4076f289
MK
66
67 int aio_fildes; /* File descriptor */
68 off_t aio_offset; /* File offset */
69 volatile void *aio_buf; /* Location of buffer */
70 size_t aio_nbytes; /* Length of transfer */
71 int aio_reqprio; /* Request priority */
72 struct sigevent aio_sigevent; /* Notification method */
73 int aio_lio_opcode; /* Operation to be performed;
74 lio_listio() only */
75
d064d41a 76 /* Various implementation\-internal fields not shown */
4076f289
MK
77};
78
836830b4 79/* Operation codes for \(aqaio_lio_opcode\(aq: */
4076f289
MK
80
81enum { LIO_READ, LIO_WRITE, LIO_NOP };
b8302363 82.EE
4076f289 83.in
38db2ef4 84.PP
4076f289 85The fields of this structure are as follows:
0019177e 86.TP
f3f7957b 87.I aio_fildes
4076f289
MK
88The file descriptor on which the I/O operation is to be performed.
89.TP
90.I aio_offset
91This is the file offset at which the I/O operation is to be performed.
92.TP
93.I aio_buf
94This is the buffer used to transfer data for a read or write operation.
95.TP
96.I aio_nbytes
97This is the size of the buffer pointed to by
98.IR aio_buf .
99.TP
100.I aio_reqprio
101This field specifies a value that is subtracted
102from the calling thread's real-time priority in order to
d46da242 103determine the priority for execution of this I/O request (see
4076f289 104.BR pthread_setschedparam (3)).
59e9285d 105The specified value must be between 0 and the value returned by
4076f289 106.IR sysconf(_SC_AIO_PRIO_DELTA_MAX) .
d46da242 107This field is ignored for file synchronization operations.
4076f289
MK
108.TP
109.I aio_sigevent
110This field is a structure that specifies how the caller is
111to be notified when the asynchronous I/O operation completes.
112Possible values for
1ae6b2c7 113.I aio_sigevent.sigev_notify
4076f289
MK
114are
115.BR SIGEV_NONE ,
116.BR SIGEV_SIGNAL ,
117and
118.BR SIGEV_THREAD .
119See
120.BR sigevent (7)
121for further details.
122.TP
123.I aio_lio_opcode
124The type of operation to be performed; used only for
125.BR lio_listio (3).
126.PP
127In addition to the standard functions listed above,
128the GNU C library provides the following extension to the POSIX AIO API:
0019177e 129.TP
4076f289
MK
130.BR aio_init (3)
131Set parameters for tuning the behavior of the glibc POSIX AIO implementation.
7484d5a7
MK
132.SH ERRORS
133.TP
134.B EINVAL
135The
136.I aio_reqprio
137field of the
138.I aiocb
139structure was less than 0,
140or was greater than the limit returned by the call
141.IR sysconf(_SC_AIO_PRIO_DELTA_MAX) .
142.SH VERSIONS
143The POSIX AIO interfaces are provided by glibc since version 2.1.
144.SH CONFORMING TO
145POSIX.1-2001, POSIX.1-2008.
4076f289
MK
146.SH NOTES
147It is a good idea to zero out the control block buffer before use (see
148.BR memset (3)).
149The control block buffer and the buffer pointed to by
150.I aio_buf
151must not be changed while the I/O operation is in progress.
152These buffers must remain valid until the I/O operation completes.
a721e8b2 153.PP
4076f289
MK
154Simultaneous asynchronous read or write operations using the same
155.I aiocb
156structure yield undefined results.
a721e8b2 157.PP
7fac88a9 158The current Linux POSIX AIO implementation is provided in user space by glibc.
4076f289
MK
159This has a number of limitations, most notably that maintaining multiple
160threads to perform I/O operations is expensive and scales poorly.
161Work has been in progress for some time on a kernel
162state-machine-based implementation of asynchronous I/O
163(see
164.BR io_submit (2),
165.BR io_setup (2),
166.BR io_cancel (2),
167.BR io_destroy (2),
168.BR io_getevents (2)),
169but this implementation hasn't yet matured to the point where
170the POSIX AIO implementation can be completely
171reimplemented using the kernel system calls.
172.\" http://lse.sourceforge.net/io/aio.html
173.\" http://lse.sourceforge.net/io/aionotes.txt
174.\" http://lwn.net/Articles/148755/
a14af333 175.SH EXAMPLES
4076f289
MK
176The program below opens each of the files named in its command-line
177arguments and queues a request on the resulting file descriptor using
178.BR aio_read (3).
179The program then loops,
180periodically monitoring each of the I/O operations
181that is still in progress using
182.BR aio_error (3).
183Each of the I/O requests is set up to provide notification by delivery
184of a signal.
185After all I/O requests have completed,
186the program retrieves their status using
187.BR aio_return (3).
a721e8b2 188.PP
4076f289
MK
189The
190.B SIGQUIT
d1a71985 191signal (generated by typing control-\e) causes the program to request
1f08fc80 192cancelation of each of the outstanding requests using
4076f289 193.BR aio_cancel (3).
a721e8b2 194.PP
4076f289
MK
195Here is an example of what we might see when running this program.
196In this example, the program queues two requests to standard input,
197and these are satisfied by two lines of input containing
198"abc" and "x".
a721e8b2 199.PP
4076f289 200.in +4n
b8302363 201.EX
4076f289
MK
202$ \fB./a.out /dev/stdin /dev/stdin\fP
203opened /dev/stdin on descriptor 3
204opened /dev/stdin on descriptor 4
205aio_error():
206 for request 0 (descriptor 3): In progress
207 for request 1 (descriptor 4): In progress
208\fBabc\fP
209I/O completion signal received
210aio_error():
211 for request 0 (descriptor 3): I/O succeeded
212 for request 1 (descriptor 4): In progress
213aio_error():
214 for request 1 (descriptor 4): In progress
215\fBx\fP
216I/O completion signal received
217aio_error():
218 for request 1 (descriptor 4): I/O succeeded
219All I/O requests completed
220aio_return():
221 for request 0 (descriptor 3): 4
222 for request 1 (descriptor 4): 2
b8302363 223.EE
4076f289
MK
224.in
225.SS Program source
226\&
e7d0bb47 227.EX
ce108729 228#include <fcntl.h>
4076f289
MK
229#include <stdlib.h>
230#include <unistd.h>
231#include <stdio.h>
232#include <errno.h>
233#include <aio.h>
234#include <signal.h>
235
236#define BUF_SIZE 20 /* Size of buffers for read operations */
237
238#define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); } while (0)
239
4076f289
MK
240struct ioRequest { /* Application\-defined structure for tracking
241 I/O requests */
242 int reqNum;
243 int status;
244 struct aiocb *aiocbp;
245};
246
247static volatile sig_atomic_t gotSIGQUIT = 0;
248 /* On delivery of SIGQUIT, we attempt to
249 cancel all outstanding I/O requests */
250
251static void /* Handler for SIGQUIT */
252quitHandler(int sig)
253{
254 gotSIGQUIT = 1;
255}
256
257#define IO_SIGNAL SIGUSR1 /* Signal used to notify I/O completion */
258
259static void /* Handler for I/O completion signal */
260aioSigHandler(int sig, siginfo_t *si, void *ucontext)
261{
d064d41a 262 if (si\->si_code == SI_ASYNCIO) {
d1a71985 263 write(STDOUT_FILENO, "I/O completion signal received\en", 31);
4076f289 264
148c6e74
AG
265 /* The corresponding ioRequest structure would be available as
266 struct ioRequest *ioReq = si\->si_value.sival_ptr;
267 and the file descriptor would then be available via
268 ioReq\->aiocbp\->aio_fildes */
269 }
4076f289
MK
270}
271
272int
273main(int argc, char *argv[])
274{
4076f289 275 struct sigaction sa;
88893a77 276 int s;
4076f289
MK
277 int numReqs; /* Total number of queued I/O requests */
278 int openReqs; /* Number of I/O requests still in progress */
279
280 if (argc < 2) {
d1a71985 281 fprintf(stderr, "Usage: %s <pathname> <pathname>...\en",
4076f289
MK
282 argv[0]);
283 exit(EXIT_FAILURE);
284 }
285
286 numReqs = argc \- 1;
287
46b20ca1 288 /* Allocate our arrays. */
4076f289 289
48d05103 290 struct ioRequest *ioList = calloc(numReqs, sizeof(*ioList));
4076f289
MK
291 if (ioList == NULL)
292 errExit("calloc");
293
48d05103 294 struct aiocb *aiocbList = calloc(numReqs, sizeof(*aiocbList));
4076f289
MK
295 if (aiocbList == NULL)
296 errExit("calloc");
297
46b20ca1 298 /* Establish handlers for SIGQUIT and the I/O completion signal. */
4076f289
MK
299
300 sa.sa_flags = SA_RESTART;
301 sigemptyset(&sa.sa_mask);
302
303 sa.sa_handler = quitHandler;
304 if (sigaction(SIGQUIT, &sa, NULL) == \-1)
305 errExit("sigaction");
306
307 sa.sa_flags = SA_RESTART | SA_SIGINFO;
308 sa.sa_sigaction = aioSigHandler;
309 if (sigaction(IO_SIGNAL, &sa, NULL) == \-1)
310 errExit("sigaction");
311
312 /* Open each file specified on the command line, and queue
46b20ca1 313 a read request on the resulting file descriptor. */
4076f289 314
88893a77 315 for (int j = 0; j < numReqs; j++) {
4076f289
MK
316 ioList[j].reqNum = j;
317 ioList[j].status = EINPROGRESS;
318 ioList[j].aiocbp = &aiocbList[j];
319
320 ioList[j].aiocbp\->aio_fildes = open(argv[j + 1], O_RDONLY);
321 if (ioList[j].aiocbp\->aio_fildes == \-1)
322 errExit("open");
d1a71985 323 printf("opened %s on descriptor %d\en", argv[j + 1],
4076f289
MK
324 ioList[j].aiocbp\->aio_fildes);
325
326 ioList[j].aiocbp\->aio_buf = malloc(BUF_SIZE);
327 if (ioList[j].aiocbp\->aio_buf == NULL)
328 errExit("malloc");
329
330 ioList[j].aiocbp\->aio_nbytes = BUF_SIZE;
331 ioList[j].aiocbp\->aio_reqprio = 0;
332 ioList[j].aiocbp\->aio_offset = 0;
333 ioList[j].aiocbp\->aio_sigevent.sigev_notify = SIGEV_SIGNAL;
334 ioList[j].aiocbp\->aio_sigevent.sigev_signo = IO_SIGNAL;
335 ioList[j].aiocbp\->aio_sigevent.sigev_value.sival_ptr =
336 &ioList[j];
337
338 s = aio_read(ioList[j].aiocbp);
339 if (s == \-1)
340 errExit("aio_read");
341 }
342
343 openReqs = numReqs;
344
46b20ca1 345 /* Loop, monitoring status of I/O requests. */
4076f289
MK
346
347 while (openReqs > 0) {
348 sleep(3); /* Delay between each monitoring step */
349
350 if (gotSIGQUIT) {
351
352 /* On receipt of SIGQUIT, attempt to cancel each of the
353 outstanding I/O requests, and display status returned
1f08fc80 354 from the cancelation requests. */
4076f289 355
d1a71985 356 printf("got SIGQUIT; canceling I/O requests: \en");
4076f289 357
88893a77 358 for (int j = 0; j < numReqs; j++) {
4076f289
MK
359 if (ioList[j].status == EINPROGRESS) {
360 printf(" Request %d on descriptor %d:", j,
361 ioList[j].aiocbp\->aio_fildes);
362 s = aio_cancel(ioList[j].aiocbp\->aio_fildes,
363 ioList[j].aiocbp);
364 if (s == AIO_CANCELED)
d1a71985 365 printf("I/O canceled\en");
4076f289 366 else if (s == AIO_NOTCANCELED)
d1a71985 367 printf("I/O not canceled\en");
4076f289 368 else if (s == AIO_ALLDONE)
d1a71985 369 printf("I/O all done\en");
4076f289 370 else
b8c40f89 371 perror("aio_cancel");
4076f289
MK
372 }
373 }
374
375 gotSIGQUIT = 0;
376 }
377
378 /* Check the status of each I/O request that is still
46b20ca1 379 in progress. */
4076f289 380
d1a71985 381 printf("aio_error():\en");
88893a77 382 for (int j = 0; j < numReqs; j++) {
4076f289
MK
383 if (ioList[j].status == EINPROGRESS) {
384 printf(" for request %d (descriptor %d): ",
385 j, ioList[j].aiocbp\->aio_fildes);
386 ioList[j].status = aio_error(ioList[j].aiocbp);
387
388 switch (ioList[j].status) {
389 case 0:
d1a71985 390 printf("I/O succeeded\en");
4076f289
MK
391 break;
392 case EINPROGRESS:
d1a71985 393 printf("In progress\en");
4076f289
MK
394 break;
395 case ECANCELED:
d1a71985 396 printf("Canceled\en");
4076f289
MK
397 break;
398 default:
b8c40f89 399 perror("aio_error");
4076f289
MK
400 break;
401 }
402
403 if (ioList[j].status != EINPROGRESS)
404 openReqs\-\-;
405 }
406 }
407 }
408
d1a71985 409 printf("All I/O requests completed\en");
4076f289 410
46b20ca1 411 /* Check status return of all I/O requests. */
4076f289 412
d1a71985 413 printf("aio_return():\en");
88893a77 414 for (int j = 0; j < numReqs; j++) {
4076f289
MK
415 ssize_t s;
416
417 s = aio_return(ioList[j].aiocbp);
d1a71985 418 printf(" for request %d (descriptor %d): %zd\en",
8c5fcd21 419 j, ioList[j].aiocbp\->aio_fildes, s);
4076f289
MK
420 }
421
422 exit(EXIT_SUCCESS);
423}
e7d0bb47 424.EE
4076f289
MK
425.SH SEE ALSO
426.ad l
ca8a0bd2 427.nh
4076f289
MK
428.BR io_cancel (2),
429.BR io_destroy (2),
95406ae0 430.BR io_getevents (2),
3e5c319e
MK
431.BR io_setup (2),
432.BR io_submit (2),
4076f289
MK
433.BR aio_cancel (3),
434.BR aio_error (3),
435.BR aio_init (3),
436.BR aio_read (3),
437.BR aio_return (3),
438.BR aio_write (3),
173fe7e7 439.BR lio_listio (3)
a721e8b2 440.PP
692ed9b6
MK
441"Asynchronous I/O Support in Linux 2.5",
442Bhattacharya, Pratt, Pulavarty, and Morgan,
443Proceedings of the Linux Symposium, 2003,
5465ae95 444.UR https://www.kernel.org/doc/ols/2003/ols2003\-pages\-351\-366.pdf
608bf950 445.UE