malloc.3: Clarify that realloc() may move the memory block
[man-pages.git] / man7 / aio.7
blob72287be066ec78d34eca245063116540754f6b37
1 .\" Copyright (c) 2010 by Michael Kerrisk <mtk.manpages@gmail.com>
2 .\"
3 .\" %%%LICENSE_START(VERBATIM)
4 .\" Permission is granted to make and distribute verbatim copies of this
5 .\" manual provided the copyright notice and this permission notice are
6 .\" preserved on all copies.
7 .\"
8 .\" Permission is granted to copy and distribute modified versions of this
9 .\" manual under the conditions for verbatim copying, provided that the
10 .\" entire resulting derived work is distributed under the terms of a
11 .\" permission notice identical to this one.
12 .\"
13 .\" Since the Linux kernel and libraries are constantly changing, this
14 .\" manual page may be incorrect or out-of-date.  The author(s) assume no
15 .\" responsibility for errors or omissions, or for damages resulting from
16 .\" the use of the information contained herein.  The author(s) may not
17 .\" have taken the same level of care in the production of this manual,
18 .\" which is licensed free of charge, as they might when working
19 .\" professionally.
20 .\"
21 .\" Formatted or processed versions of this manual, if unaccompanied by
22 .\" the source, must acknowledge the copyright and authors of this work.
23 .\" %%%LICENSE_END
24 .\"
25 .TH AIO 7 2021-03-22 "Linux" "Linux Programmer's Manual"
26 .SH NAME
27 aio \- POSIX asynchronous I/O overview
28 .SH DESCRIPTION
29 The POSIX asynchronous I/O (AIO) interface allows applications
30 to initiate one or more I/O operations that are performed
31 asynchronously (i.e., in the background).
32 The application can elect to be notified of completion of
33 the I/O operation in a variety of ways:
34 by delivery of a signal, by instantiation of a thread,
35 or no notification at all.
36 .PP
37 The POSIX AIO interface consists of the following functions:
38 .TP
39 .BR aio_read (3)
40 Enqueue a read request.
41 This is the asynchronous analog of
42 .BR read (2).
43 .TP
44 .BR aio_write (3)
45 Enqueue a write request.
46 This is the asynchronous analog of
47 .BR write (2).
48 .TP
49 .BR aio_fsync (3)
50 Enqueue a sync request for the I/O operations on a file descriptor.
51 This is the asynchronous analog of
52 .BR fsync (2)
53 and
54 .BR fdatasync (2).
55 .TP
56 .BR aio_error (3)
57 Obtain the error status of an enqueued I/O request.
58 .TP
59 .BR aio_return (3)
60 Obtain the return status of a completed I/O request.
61 .TP
62 .BR aio_suspend (3)
63 Suspend the caller until one or more of a specified set of
64 I/O requests completes.
65 .TP
66 .BR aio_cancel (3)
67 Attempt to cancel outstanding I/O requests on a specified
68 file descriptor.
69 .TP
70 .BR lio_listio (3)
71 Enqueue multiple I/O requests using a single function call.
72 .PP
73 The
74 .I aiocb
75 ("asynchronous I/O control block") structure defines
76 parameters that control an I/O operation.
77 An argument of this type is employed with all of the functions listed above.
78 This structure has the following form:
79 .PP
80 .in +4n
81 .EX
82 #include <aiocb.h>
84 struct aiocb {
85     /* The order of these fields is implementation\-dependent */
87     int             aio_fildes;     /* File descriptor */
88     off_t           aio_offset;     /* File offset */
89     volatile void  *aio_buf;        /* Location of buffer */
90     size_t          aio_nbytes;     /* Length of transfer */
91     int             aio_reqprio;    /* Request priority */
92     struct sigevent aio_sigevent;   /* Notification method */
93     int             aio_lio_opcode; /* Operation to be performed;
94                                        lio_listio() only */
96     /* Various implementation\-internal fields not shown */
99 /* Operation codes for \(aqaio_lio_opcode\(aq: */
101 enum { LIO_READ, LIO_WRITE, LIO_NOP };
105 The fields of this structure are as follows:
107 .I aio_fildes
108 The file descriptor on which the I/O operation is to be performed.
110 .I aio_offset
111 This is the file offset at which the I/O operation is to be performed.
113 .I aio_buf
114 This is the buffer used to transfer data for a read or write operation.
116 .I aio_nbytes
117 This is the size of the buffer pointed to by
118 .IR aio_buf .
120 .I aio_reqprio
121 This field specifies a value that is subtracted
122 from the calling thread's real-time priority in order to
123 determine the priority for execution of this I/O request (see
124 .BR pthread_setschedparam (3)).
125 The specified value must be between 0 and the value returned by
126 .IR sysconf(_SC_AIO_PRIO_DELTA_MAX) .
127 This field is ignored for file synchronization operations.
129 .I aio_sigevent
130 This field is a structure that specifies how the caller is
131 to be notified when the asynchronous I/O operation completes.
132 Possible values for
133 .IR aio_sigevent.sigev_notify
135 .BR SIGEV_NONE ,
136 .BR SIGEV_SIGNAL ,
138 .BR SIGEV_THREAD .
140 .BR sigevent (7)
141 for further details.
143 .I aio_lio_opcode
144 The type of operation to be performed; used only for
145 .BR lio_listio (3).
147 In addition to the standard functions listed above,
148 the GNU C library provides the following extension to the POSIX AIO API:
150 .BR aio_init (3)
151 Set parameters for tuning the behavior of the glibc POSIX AIO implementation.
152 .SH ERRORS
154 .B EINVAL
156 .I aio_reqprio
157 field of the
158 .I aiocb
159 structure was less than 0,
160 or was greater than the limit returned by the call
161 .IR sysconf(_SC_AIO_PRIO_DELTA_MAX) .
162 .SH VERSIONS
163 The POSIX AIO interfaces are provided by glibc since version 2.1.
164 .SH CONFORMING TO
165 POSIX.1-2001, POSIX.1-2008.
166 .SH NOTES
167 It is a good idea to zero out the control block buffer before use (see
168 .BR memset (3)).
169 The control block buffer and the buffer pointed to by
170 .I aio_buf
171 must not be changed while the I/O operation is in progress.
172 These buffers must remain valid until the I/O operation completes.
174 Simultaneous asynchronous read or write operations using the same
175 .I aiocb
176 structure yield undefined results.
178 The current Linux POSIX AIO implementation is provided in user space by glibc.
179 This has a number of limitations, most notably that maintaining multiple
180 threads to perform I/O operations is expensive and scales poorly.
181 Work has been in progress for some time on a kernel
182 state-machine-based implementation of asynchronous I/O
183 (see
184 .BR io_submit (2),
185 .BR io_setup (2),
186 .BR io_cancel (2),
187 .BR io_destroy (2),
188 .BR io_getevents (2)),
189 but this implementation hasn't yet matured to the point where
190 the POSIX AIO implementation can be completely
191 reimplemented using the kernel system calls.
192 .\" http://lse.sourceforge.net/io/aio.html
193 .\" http://lse.sourceforge.net/io/aionotes.txt
194 .\" http://lwn.net/Articles/148755/
195 .SH EXAMPLES
196 The program below opens each of the files named in its command-line
197 arguments and queues a request on the resulting file descriptor using
198 .BR aio_read (3).
199 The program then loops,
200 periodically monitoring each of the I/O operations
201 that is still in progress using
202 .BR aio_error (3).
203 Each of the I/O requests is set up to provide notification by delivery
204 of a signal.
205 After all I/O requests have completed,
206 the program retrieves their status using
207 .BR aio_return (3).
210 .B SIGQUIT
211 signal (generated by typing control-\e) causes the program to request
212 cancellation of each of the outstanding requests using
213 .BR aio_cancel (3).
215 Here is an example of what we might see when running this program.
216 In this example, the program queues two requests to standard input,
217 and these are satisfied by two lines of input containing
218 "abc" and "x".
220 .in +4n
222 $ \fB./a.out /dev/stdin /dev/stdin\fP
223 opened /dev/stdin on descriptor 3
224 opened /dev/stdin on descriptor 4
225 aio_error():
226     for request 0 (descriptor 3): In progress
227     for request 1 (descriptor 4): In progress
228 \fBabc\fP
229 I/O completion signal received
230 aio_error():
231     for request 0 (descriptor 3): I/O succeeded
232     for request 1 (descriptor 4): In progress
233 aio_error():
234     for request 1 (descriptor 4): In progress
235 \fBx\fP
236 I/O completion signal received
237 aio_error():
238     for request 1 (descriptor 4): I/O succeeded
239 All I/O requests completed
240 aio_return():
241     for request 0 (descriptor 3): 4
242     for request 1 (descriptor 4): 2
245 .SS Program source
248 #include <fcntl.h>
249 #include <stdlib.h>
250 #include <unistd.h>
251 #include <stdio.h>
252 #include <errno.h>
253 #include <aio.h>
254 #include <signal.h>
256 #define BUF_SIZE 20     /* Size of buffers for read operations */
258 #define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); } while (0)
260 struct ioRequest {      /* Application\-defined structure for tracking
261                            I/O requests */
262     int           reqNum;
263     int           status;
264     struct aiocb *aiocbp;
267 static volatile sig_atomic_t gotSIGQUIT = 0;
268                         /* On delivery of SIGQUIT, we attempt to
269                            cancel all outstanding I/O requests */
271 static void             /* Handler for SIGQUIT */
272 quitHandler(int sig)
274     gotSIGQUIT = 1;
277 #define IO_SIGNAL SIGUSR1   /* Signal used to notify I/O completion */
279 static void                 /* Handler for I/O completion signal */
280 aioSigHandler(int sig, siginfo_t *si, void *ucontext)
282     if (si\->si_code == SI_ASYNCIO) {
283         write(STDOUT_FILENO, "I/O completion signal received\en", 31);
285         /* The corresponding ioRequest structure would be available as
286                struct ioRequest *ioReq = si\->si_value.sival_ptr;
287            and the file descriptor would then be available via
288                ioReq\->aiocbp\->aio_fildes */
289     }
293 main(int argc, char *argv[])
295     struct sigaction sa;
296     int s;
297     int numReqs;        /* Total number of queued I/O requests */
298     int openReqs;       /* Number of I/O requests still in progress */
300     if (argc < 2) {
301         fprintf(stderr, "Usage: %s <pathname> <pathname>...\en",
302                 argv[0]);
303         exit(EXIT_FAILURE);
304     }
306     numReqs = argc \- 1;
308     /* Allocate our arrays. */
310     struct ioRequest *ioList = calloc(numReqs, sizeof(*ioList));
311     if (ioList == NULL)
312         errExit("calloc");
314     struct aiocb *aiocbList = calloc(numReqs, sizeof(*aiocbList));
315     if (aiocbList == NULL)
316         errExit("calloc");
318     /* Establish handlers for SIGQUIT and the I/O completion signal. */
320     sa.sa_flags = SA_RESTART;
321     sigemptyset(&sa.sa_mask);
323     sa.sa_handler = quitHandler;
324     if (sigaction(SIGQUIT, &sa, NULL) == \-1)
325         errExit("sigaction");
327     sa.sa_flags = SA_RESTART | SA_SIGINFO;
328     sa.sa_sigaction = aioSigHandler;
329     if (sigaction(IO_SIGNAL, &sa, NULL) == \-1)
330         errExit("sigaction");
332     /* Open each file specified on the command line, and queue
333        a read request on the resulting file descriptor. */
335     for (int j = 0; j < numReqs; j++) {
336         ioList[j].reqNum = j;
337         ioList[j].status = EINPROGRESS;
338         ioList[j].aiocbp = &aiocbList[j];
340         ioList[j].aiocbp\->aio_fildes = open(argv[j + 1], O_RDONLY);
341         if (ioList[j].aiocbp\->aio_fildes == \-1)
342             errExit("open");
343         printf("opened %s on descriptor %d\en", argv[j + 1],
344                 ioList[j].aiocbp\->aio_fildes);
346         ioList[j].aiocbp\->aio_buf = malloc(BUF_SIZE);
347         if (ioList[j].aiocbp\->aio_buf == NULL)
348             errExit("malloc");
350         ioList[j].aiocbp\->aio_nbytes = BUF_SIZE;
351         ioList[j].aiocbp\->aio_reqprio = 0;
352         ioList[j].aiocbp\->aio_offset = 0;
353         ioList[j].aiocbp\->aio_sigevent.sigev_notify = SIGEV_SIGNAL;
354         ioList[j].aiocbp\->aio_sigevent.sigev_signo = IO_SIGNAL;
355         ioList[j].aiocbp\->aio_sigevent.sigev_value.sival_ptr =
356                                 &ioList[j];
358         s = aio_read(ioList[j].aiocbp);
359         if (s == \-1)
360             errExit("aio_read");
361     }
363     openReqs = numReqs;
365     /* Loop, monitoring status of I/O requests. */
367     while (openReqs > 0) {
368         sleep(3);       /* Delay between each monitoring step */
370         if (gotSIGQUIT) {
372             /* On receipt of SIGQUIT, attempt to cancel each of the
373                outstanding I/O requests, and display status returned
374                from the cancellation requests. */
376             printf("got SIGQUIT; canceling I/O requests: \en");
378             for (int j = 0; j < numReqs; j++) {
379                 if (ioList[j].status == EINPROGRESS) {
380                     printf("    Request %d on descriptor %d:", j,
381                             ioList[j].aiocbp\->aio_fildes);
382                     s = aio_cancel(ioList[j].aiocbp\->aio_fildes,
383                             ioList[j].aiocbp);
384                     if (s == AIO_CANCELED)
385                         printf("I/O canceled\en");
386                     else if (s == AIO_NOTCANCELED)
387                         printf("I/O not canceled\en");
388                     else if (s == AIO_ALLDONE)
389                         printf("I/O all done\en");
390                     else
391                         perror("aio_cancel");
392                 }
393             }
395             gotSIGQUIT = 0;
396         }
398         /* Check the status of each I/O request that is still
399            in progress. */
401         printf("aio_error():\en");
402         for (int j = 0; j < numReqs; j++) {
403             if (ioList[j].status == EINPROGRESS) {
404                 printf("    for request %d (descriptor %d): ",
405                         j, ioList[j].aiocbp\->aio_fildes);
406                 ioList[j].status = aio_error(ioList[j].aiocbp);
408                 switch (ioList[j].status) {
409                 case 0:
410                     printf("I/O succeeded\en");
411                     break;
412                 case EINPROGRESS:
413                     printf("In progress\en");
414                     break;
415                 case ECANCELED:
416                     printf("Canceled\en");
417                     break;
418                 default:
419                     perror("aio_error");
420                     break;
421                 }
423                 if (ioList[j].status != EINPROGRESS)
424                     openReqs\-\-;
425             }
426         }
427     }
429     printf("All I/O requests completed\en");
431     /* Check status return of all I/O requests. */
433     printf("aio_return():\en");
434     for (int j = 0; j < numReqs; j++) {
435         ssize_t s;
437         s = aio_return(ioList[j].aiocbp);
438         printf("    for request %d (descriptor %d): %zd\en",
439                 j, ioList[j].aiocbp\->aio_fildes, s);
440     }
442     exit(EXIT_SUCCESS);
445 .SH SEE ALSO
446 .ad l
448 .BR io_cancel (2),
449 .BR io_destroy (2),
450 .BR io_getevents (2),
451 .BR io_setup (2),
452 .BR io_submit (2),
453 .BR aio_cancel (3),
454 .BR aio_error (3),
455 .BR aio_init (3),
456 .BR aio_read (3),
457 .BR aio_return (3),
458 .BR aio_write (3),
459 .BR lio_listio (3)
461 "Asynchronous I/O Support in Linux 2.5",
462 Bhattacharya, Pratt, Pulavarty, and Morgan,
463 Proceedings of the Linux Symposium, 2003,
464 .UR https://www.kernel.org/doc/ols/2003/ols2003\-pages\-351\-366.pdf