2 .\" Copyright (c) 2010 by Michael Kerrisk <mtk.manpages@gmail.com>
4 .\" %%%LICENSE_START(VERBATIM)
5 .\" Permission is granted to make and distribute verbatim copies of this
6 .\" manual provided the copyright notice and this permission notice are
7 .\" preserved on all copies.
9 .\" Permission is granted to copy and distribute modified versions of this
10 .\" manual under the conditions for verbatim copying, provided that the
11 .\" entire resulting derived work is distributed under the terms of a
12 .\" permission notice identical to this one.
14 .\" Since the Linux kernel and libraries are constantly changing, this
15 .\" manual page may be incorrect or out-of-date. The author(s) assume no
16 .\" responsibility for errors or omissions, or for damages resulting from
17 .\" the use of the information contained herein. The author(s) may not
18 .\" have taken the same level of care in the production of this manual,
19 .\" which is licensed free of charge, as they might when working
22 .\" Formatted or processed versions of this manual, if unaccompanied by
23 .\" the source, must acknowledge the copyright and authors of this work.
26 .\"*******************************************************************
28 .\" This file was generated with po4a. Translate the source file.
30 .\"*******************************************************************
32 .\" Japanese Version Copyright (c) 2012 Akihiro MOTOKI
33 .\" all rights reserved.
34 .\" Translated 2012-05-02, Akihiro MOTOKI <amotoki@gmail.com>
36 .TH AIO 7 2012\-08\-05 Linux "Linux Programmer's Manual"
38 aio \- POSIX 非同期 I/O の概要
40 POSIX 非同期 (AIO) インターフェースを使うと、アプリケーションは、非同期
41 に (つまり、バックグラウンドで) 実行されるI/O 操作を一つ以上発行できる
42 ようになる。アプリケーションは I/O 操作の完了の通知方法を選択することが
43 できる。選択できる通知方法は、シグナルの配送、スレッドの起動、通知を行
46 POSIX AIO インターフェースは以下の関数で構成されている。
50 \fBread\fP(2) の非同期版である。
54 \fBwrite\fP(2) の非同期版である。
57 ファイルディスクリプタに対して行われた I/O 操作の
58 同期 (sync) リクエストをキューに入れる。
59 \fBfsync\fP(2) や \fBfdatasync\fP(2) の非同期版である。
62 キューに入れられた I/O リクエストのエラー状態を取得する。
65 完了した I/O リクエストの終了ステータスを取得する。
68 指定された I/O リクエストの集合 (要素は一つ以上) が完了するまで、
69 呼び出し側の実行を停止 (suspend) する。
73 完了していない I/O リクエストのキャンセルを試みる。
76 一回の関数呼び出しで複数の I/O リクエストをキューに入れる。
78 \fIaiocb\fP ("非同期 I/O 制御ブロック (asynchronous I/O control block)")
79 構造体は、I/O 操作を制御するパラメータを定義する。この型の引き数は上記
80 の全ての関数で使用されている。この構造体は以下の通りである。
87 /* The order of these fields is implementation\-dependent */
89 int aio_fildes; /* File descriptor */
90 off_t aio_offset; /* File offset */
91 volatile void *aio_buf; /* Location of buffer */
92 size_t aio_nbytes; /* Length of transfer */
93 int aio_reqprio; /* Request priority */
94 struct sigevent aio_sigevent; /* Notification method */
95 int aio_lio_opcode; /* Operation to be performed;
98 /* Various implementation\-internal fields not shown */
101 /* Operation codes for \(aqaio_lio_opcode\(aq: */
103 enum { LIO_READ, LIO_WRITE, LIO_NOP };
107 この構造体のフィールドは以下の通りである。
110 I/O 操作の実行対象となるファイルディスクリプタ。
113 I/O 操作を行うファイルオフセットを示す。
116 読み出し操作、書き込み操作でデータ転送に使用されるバッファ。
119 \fIaio_buf\fP が指すバッファのサイズ。
122 このフィールドでは、呼び出したスレッドのリアルタイム優先度から
123 減算する値を指定する。この I/O リクエストの実行の優先度を
124 決定するために使用される (\fBpthread_setschedparam\fP(3) 参照)。
125 指定する値は 0 と \fIsysconf(_SC_AIO_PRIO_DELTA_MAX)\fP が返す値の間で
126 なければならない。このフィールドは、ファイル同期操作では無視される。
129 このフィールドは、非同期 I/O 操作が完了した際に呼び出し側に
130 どのように通知を行うかを指定する構造体である。
131 \fIaio_sigevent.sigev_notify\fP に指定できる値は、
132 \fBSIGEV_NONE\fP, \fBSIGEV_SIGNAL\fP, \fBSIGEV_THREAD\fP である。
133 詳細は \fBsigevent\fP(7) を参照。
137 \fBlio_listio\fP(3) でのみ使用される。
139 上記のリストにある標準の関数に加えて、GNU C ライブラリでは
140 以下に示す POSIX AIO API に対する拡張が提供されている。
143 glibc の POSIX AIO 実装の動作を調整するパラメータを設定する。
147 \fIaiocb\fP 構造体の \fIaio_reqprio\fP フィールドが、0 より小さいか、
148 \fIsysconf(_SC_AIO_PRIO_DELTA_MAX)\fP が返す上限よりも大きかった。
150 POSIX AIO インターフェイスは glibc バージョン 2.1 以降で提供されている。
152 POSIX.1\-2001, POSIX.1\-2008.
154 使用前に制御ブロックバッファを 0 で埋めるのはよい考えである
155 (\fBmemset\fP(3) 参照)。I/O 操作が実行中の間は、制御ブロックバッファと
156 \fIaio_buf\fP が指すバッファを変更してはならない。I/O 操作が完了するまで、
157 これらのバッファは有効な状態に保たなければならない。
159 同じ \fIaiocb\fP 構造体を使って、同時に複数の非同期の読み出し操作や
160 書き込み操作を行った場合に、どのような結果になるかは未定義である。
162 .\" http://lse.sourceforge.net/io/aio.html
163 .\" http://lse.sourceforge.net/io/aionotes.txt
164 .\" http://lwn.net/Articles/148755/
165 現在の Linux では、POSIX AIO 実装は glibc によりユーザ空間で提供
166 されている。このため、制限がいくつかあり、最も顕著なものは、I/O 操作を
167 実行する複数のスレッドの管理コストが高く、スケーラビリティに欠けること
168 である。しばらくの間、カーネルのステートマシンによる非同期 I/O の実装
169 の作業が行われているが (\fBio_submit\fP(2), \fBio_setup\fP(2),
170 \fBio_cancel\fP(2), \fBio_destroy\fP(2), \fBio_getevents\fP(2) 参照)、
171 この実装はまだ POSIX AIO 実装をカーネルシステムコールにより
174 下記のプログラムは、コマンドライン引き数で指定された名前のファイルを
175 それぞれオープンし、得られたファイルディスクリプタに対するリクエストを
176 \fBaio_read\fP(3) を使ってキューに入れる。その後、このプログラムはループに
177 入り、定期的に \fBaio_error\fP(3) を使ってまだ実行中の各 I/O 操作を監視す
178 る。各 I/O リクエストは、シグナルの配送による完了通知が行われるように設
179 定される。全ての I/O リクエストが完了した後、\fBaio_return\fP(3) を使って
182 \fBSIGQUIT\fP シグナル (control\-\e をタイプすると生成できる) を送ると、
183 このプログラムは \fBaio_cancel\fP(3) を使って
184 完了していない各リクエストにキャンセル要求を送る。
186 以下はこのプログラムを実行した際の出力例である。
187 この例では、標準入力に対して 2 つのリクエストを行い、
188 "abc" と "x" という 2 行の入力を行っている。
192 $ \fB./a.out /dev/stdin /dev/stdin\fP
193 opened /dev/stdin on descriptor 3
194 opened /dev/stdin on descriptor 4
196 for request 0 (descriptor 3): In progress
197 for request 1 (descriptor 4): In progress
199 I/O completion signal received
201 for request 0 (descriptor 3): I/O succeeded
202 for request 1 (descriptor 4): In progress
204 for request 1 (descriptor 4): In progress
206 I/O completion signal received
208 for request 1 (descriptor 4): I/O succeeded
209 All I/O requests completed
211 for request 0 (descriptor 3): 4
212 for request 1 (descriptor 4): 2
225 #define BUF_SIZE 20 /* Size of buffers for read operations */
227 #define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); } while (0)
229 #define errMsg(msg) do { perror(msg); } while (0)
231 struct ioRequest { /* Application\-defined structure for tracking
235 struct aiocb *aiocbp;
238 static volatile sig_atomic_t gotSIGQUIT = 0;
239 /* On delivery of SIGQUIT, we attempt to
240 cancel all outstanding I/O requests */
242 static void /* Handler for SIGQUIT */
248 #define IO_SIGNAL SIGUSR1 /* Signal used to notify I/O completion */
250 static void /* Handler for I/O completion signal */
251 aioSigHandler(int sig, siginfo_t *si, void *ucontext)
253 write(STDOUT_FILENO, "I/O completion signal received\en", 31);
255 /* The corresponding ioRequest structure would be available as
256 struct ioRequest *ioReq = si\->si_value.sival_ptr;
257 and the file descriptor would then be available via
258 ioReq\->aiocbp\->aio_fildes */
262 main(int argc, char *argv[])
264 struct ioRequest *ioList;
265 struct aiocb *aiocbList;
268 int numReqs; /* Total number of queued I/O requests */
269 int openReqs; /* Number of I/O requests still in progress */
272 fprintf(stderr, "Usage: %s <pathname> <pathname>...\en",
279 /* Allocate our arrays */
281 ioList = calloc(numReqs, sizeof(struct ioRequest));
285 aiocbList = calloc(numReqs, sizeof(struct aiocb));
286 if (aiocbList == NULL)
289 /* Establish handlers for SIGQUIT and the I/O completion signal */
291 sa.sa_flags = SA_RESTART;
292 sigemptyset(&sa.sa_mask);
294 sa.sa_handler = quitHandler;
295 if (sigaction(SIGQUIT, &sa, NULL) == \-1)
296 errExit("sigaction");
298 sa.sa_flags = SA_RESTART | SA_SIGINFO;
299 sa.sa_sigaction = aioSigHandler;
300 if (sigaction(IO_SIGNAL, &sa, NULL) == \-1)
301 errExit("sigaction");
303 /* Open each file specified on the command line, and queue
304 a read request on the resulting file descriptor */
306 for (j = 0; j < numReqs; j++) {
307 ioList[j].reqNum = j;
308 ioList[j].status = EINPROGRESS;
309 ioList[j].aiocbp = &aiocbList[j];
311 ioList[j].aiocbp\->aio_fildes = open(argv[j + 1], O_RDONLY);
312 if (ioList[j].aiocbp\->aio_fildes == \-1)
314 printf("opened %s on descriptor %d\en", argv[j + 1],
315 ioList[j].aiocbp\->aio_fildes);
317 ioList[j].aiocbp\->aio_buf = malloc(BUF_SIZE);
318 if (ioList[j].aiocbp\->aio_buf == NULL)
321 ioList[j].aiocbp\->aio_nbytes = BUF_SIZE;
322 ioList[j].aiocbp\->aio_reqprio = 0;
323 ioList[j].aiocbp\->aio_offset = 0;
324 ioList[j].aiocbp\->aio_sigevent.sigev_notify = SIGEV_SIGNAL;
325 ioList[j].aiocbp\->aio_sigevent.sigev_signo = IO_SIGNAL;
326 ioList[j].aiocbp\->aio_sigevent.sigev_value.sival_ptr =
329 s = aio_read(ioList[j].aiocbp);
336 /* Loop, monitoring status of I/O requests */
338 while (openReqs > 0) {
339 sleep(3); /* Delay between each monitoring step */
343 /* On receipt of SIGQUIT, attempt to cancel each of the
344 outstanding I/O requests, and display status returned
345 from the cancellation requests */
347 printf("got SIGQUIT; canceling I/O requests: \en");
349 for (j = 0; j < numReqs; j++) {
350 if (ioList[j].status == EINPROGRESS) {
351 printf(" Request %d on descriptor %d:", j,
352 ioList[j].aiocbp\->aio_fildes);
353 s = aio_cancel(ioList[j].aiocbp\->aio_fildes,
355 if (s == AIO_CANCELED)
356 printf("I/O canceled\en");
357 else if (s == AIO_NOTCANCELED)
358 printf("I/O not canceled\en");
359 else if (s == AIO_ALLDONE)
360 printf("I/O all done\en");
362 errMsg("aio_cancel");
369 /* Check the status of each I/O request that is still
372 printf("aio_error():\en");
373 for (j = 0; j < numReqs; j++) {
374 if (ioList[j].status == EINPROGRESS) {
375 printf(" for request %d (descriptor %d): ",
376 j, ioList[j].aiocbp\->aio_fildes);
377 ioList[j].status = aio_error(ioList[j].aiocbp);
379 switch (ioList[j].status) {
381 printf("I/O succeeded\en");
384 printf("In progress\en");
387 printf("Canceled\en");
394 if (ioList[j].status != EINPROGRESS)
400 printf("All I/O requests completed\en");
402 /* Check status return of all I/O requests */
404 printf("aio_return():\en");
405 for (j = 0; j < numReqs; j++) {
408 s = aio_return(ioList[j].aiocbp);
409 printf(" for request %d (descriptor %d): %ld\en",
410 j, ioList[j].aiocbp\->aio_fildes, (long) s);
419 \fBio_cancel\fP(2), \fBio_destroy\fP(2), \fBio_getevents\fP(2), \fBio_setup\fP(2),
420 \fBio_submit\fP(2), \fBaio_cancel\fP(3), \fBaio_error\fP(3), \fBaio_init\fP(3),
421 \fBaio_read\fP(3), \fBaio_return\fP(3), \fBaio_write\fP(3), \fBlio_listio\fP(3)
423 .UR http://www.squid\-cache.org\:/~adrian\:/Reprint\-Pulavarty\-OLS2003.pdf
426 この man ページは Linux \fIman\-pages\fP プロジェクトのリリース 3.53 の一部
427 である。プロジェクトの説明とバグ報告に関する情報は
428 http://www.kernel.org/doc/man\-pages/ に書かれている。