OSDN Git Service

(split) DP: release pages (catch up to 3.50).
[linuxjm/LDP_man-pages.git] / release / man7 / aio.7
1 .\" t
2 .\" Copyright (c) 2010 by Michael Kerrisk <mtk.manpages@gmail.com>
3 .\"
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.
8 .\"
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.
13 .\"
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
20 .\" professionally.
21 .\"
22 .\" Formatted or processed versions of this manual, if unaccompanied by
23 .\" the source, must acknowledge the copyright and authors of this work.
24 .\" %%%LICENSE_END
25 .\"
26 .\"*******************************************************************
27 .\"
28 .\" This file was generated with po4a. Translate the source file.
29 .\"
30 .\"*******************************************************************
31 .TH AIO 7 2012\-08\-05 Linux "Linux Programmer's Manual"
32 .SH 名前
33 aio \- POSIX 非同期 I/O の概要
34 .SH 説明
35 POSIX 非同期 (AIO) インターフェースを使うと、アプリケーションは、非同期
36 に (つまり、バックグラウンドで) 実行されるI/O 操作を一つ以上発行できる
37 ようになる。アプリケーションは I/O 操作の完了の通知方法を選択することが
38 できる。選択できる通知方法は、シグナルの配送、スレッドの起動、通知を行
39 わないである。
40
41 POSIX AIO インターフェースは以下の関数で構成されている。
42 .TP  16
43 \fBaio_read\fP(3)
44 読み出しリクエストをキューに入れる。
45 \fBread\fP(2) の非同期版である。
46 .TP 
47 \fBaio_write\fP(3)
48 書き込みリクエストをキューに入れる。
49 \fBwrite\fP(2) の非同期版である。
50 .TP 
51 \fBaio_fsync\fP(3)
52 ファイルディスクリプタに対して行われた I/O 操作の
53 同期 (sync) リクエストをキューに入れる。
54 \fBfsync\fP(2) や \fBfdatasync\fP(2) の非同期版である。
55 .TP 
56 \fBaio_error\fP(3)
57 キューに入れられた I/O リクエストのエラー状態を取得する。
58 .TP 
59 \fBaio_return\fP(3)
60 完了した I/O リクエストの終了ステータスを取得する。
61 .TP 
62 \fBaio_suspend\fP(3)
63 指定された I/O リクエストの集合 (要素は一つ以上) が完了するまで、
64 呼び出し側の実行を停止 (suspend) する。
65 .TP 
66 \fBaio_cancel\fP(3)
67 指定されたファイルディスクリプタに関する
68 完了していない I/O リクエストのキャンセルを試みる。
69 .TP 
70 \fBlio_listio\fP(3)
71 一回の関数呼び出しで複数の I/O リクエストをキューに入れる。
72 .PP
73 \fIaiocb\fP ("非同期 I/O 制御ブロック (asynchronous I/O control block)")
74 構造体は、I/O 操作を制御するパラメータを定義する。この型の引き数は上記
75 の全ての関数で使用されている。この構造体は以下の通りである。
76 .PP
77 .in +4n
78 .nf
79 #include <aiocb.h>
80
81 struct aiocb {
82     /* The order of these fields is implementation\-dependent */
83
84     int             aio_fildes;     /* File descriptor */
85     off_t           aio_offset;     /* File offset */
86     volatile void  *aio_buf;        /* Location of buffer */
87     size_t          aio_nbytes;     /* Length of transfer */
88     int             aio_reqprio;    /* Request priority */
89     struct sigevent aio_sigevent;   /* Notification method */
90     int             aio_lio_opcode; /* Operation to be performed;
91                                        lio_listio() only */
92
93     /* Various implementation\-internal fields not shown */
94 };
95
96 /* Operation codes for \(aqaio_lio_opcode\(aq: */
97
98 enum { LIO_READ, LIO_WRITE, LIO_NOP };
99
100 .fi
101 .in
102 この構造体のフィールドは以下の通りである。
103 .TP  16
104 \fIaio_filedes\fP
105 I/O 操作の実行対象となるファイルディスクリプタ。
106 .TP 
107 \fIaio_offset\fP
108 I/O 操作を行うファイルオフセットを示す。
109 .TP 
110 \fIaio_buf\fP
111 読み出し操作、書き込み操作でデータ転送に使用されるバッファ。
112 .TP 
113 \fIaio_nbytes\fP
114 \fIaio_buf\fP が指すバッファのサイズ。
115 .TP 
116 \fIaio_reqprio\fP
117 このフィールドでは、呼び出したスレッドのリアルタイム優先度から
118 減算する値を指定する。この I/O リクエストの実行の優先度を
119 決定するために使用される (\fBpthread_setschedparam\fP(3) 参照)。
120 指定する値は 0 と \fIsysconf(_SC_AIO_PRIO_DELTA_MAX)\fP が返す値の間で
121 なければならない。このフィールドは、ファイル同期操作では無視される。
122 .TP 
123 \fIaio_sigevent\fP
124 このフィールドは、非同期 I/O 操作が完了した際に呼び出し側に
125 どのように通知を行うかを指定する構造体である。
126 \fIaio_sigevent.sigev_notify\fP に指定できる値は、
127 \fBSIGEV_NONE\fP, \fBSIGEV_SIGNAL\fP, \fBSIGEV_THREAD\fP である。
128 詳細は \fBsigevent\fP(7) を参照。
129 .TP 
130 \fIaio_lio_opcode\fP
131 実行される操作の種別。
132 \fBlio_listio\fP(3) でのみ使用される。
133 .PP
134 上記のリストにある標準の関数に加えて、GNU C ライブラリでは
135 以下に示す POSIX AIO API に対する拡張が提供されている。
136 .TP  16
137 \fBaio_init\fP(3)
138 glibc の POSIX AIO 実装の動作を調整するパラメータを設定する。
139 .SH エラー
140 .TP 
141 \fBEINVAL\fP
142 \fIaiocb\fP 構造体の \fIaio_reqprio\fP フィールドが、0 より小さいか、
143 \fIsysconf(_SC_AIO_PRIO_DELTA_MAX)\fP が返す上限よりも大きかった。
144 .SH バージョン
145 POSIX AIO インターフェイスは glibc バージョン 2.1 以降で提供されている。
146 .SH 準拠
147 POSIX.1\-2001, POSIX.1\-2008.
148 .SH 注意
149 使用前に制御ブロックバッファを 0 で埋めるのはよい考えである
150 (\fBmemset\fP(3) 参照)。I/O 操作が実行中の間は、制御ブロックバッファと
151 \fIaio_buf\fP が指すバッファを変更してはならない。I/O 操作が完了するまで、
152 これらのバッファは有効な状態に保たなければならない。
153
154 同じ \fIaiocb\fP 構造体を使って、同時に複数の非同期の読み出し操作や
155 書き込み操作を行った場合に、どのような結果になるかは未定義である。
156
157 .\" http://lse.sourceforge.net/io/aio.html
158 .\" http://lse.sourceforge.net/io/aionotes.txt
159 .\" http://lwn.net/Articles/148755/
160 現在の Linux では、POSIX AIO 実装は glibc によりユーザ空間で提供
161 されている。このため、制限がいくつかあり、最も顕著なものは、I/O 操作を
162 実行する複数のスレッドの管理コストが高く、スケーラビリティに欠けること
163 である。しばらくの間、カーネルのステートマシンによる非同期 I/O の実装
164 の作業が行われているが (\fBio_submit\fP(2), \fBio_setup\fP(2),
165 \fBio_cancel\fP(2), \fBio_destroy\fP(2), \fBio_getevents\fP(2) 参照)、
166 この実装はまだ POSIX AIO 実装をカーネルシステムコールにより
167 再実装するほど成熟したものてはない。
168 .SH 例
169 下記のプログラムは、コマンドライン引き数で指定された名前のファイルを
170 それぞれオープンし、得られたファイルディスクリプタに対するリクエストを
171 \fBaio_read\fP(3) を使ってキューに入れる。その後、このプログラムはループに
172 入り、定期的に \fBaio_error\fP(3) を使ってまだ実行中の各 I/O 操作を監視す
173 る。各 I/O リクエストは、シグナルの配送による完了通知が行われるように設
174 定される。全ての I/O リクエストが完了した後、\fBaio_return\fP(3) を使って
175 それぞれのステータスを取得する。
176
177 \fBSIGQUIT\fP シグナル (control\-\e をタイプすると生成できる) を送ると、
178 このプログラムは \fBaio_cancel\fP(3) を使って
179 完了していない各リクエストにキャンセル要求を送る。
180
181 以下はこのプログラムを実行した際の出力例である。
182 この例では、標準入力に対して 2 つのリクエストを行い、
183 "abc" と "x" という 2 行の入力を行っている。
184
185 .in +4n
186 .nf
187 $ \fB./a.out /dev/stdin /dev/stdin\fP
188 opened /dev/stdin on descriptor 3
189 opened /dev/stdin on descriptor 4
190 aio_error():
191     for request 0 (descriptor 3): In progress
192     for request 1 (descriptor 4): In progress
193 \fBabc\fP
194 I/O completion signal received
195 aio_error():
196     for request 0 (descriptor 3): I/O succeeded
197     for request 1 (descriptor 4): In progress
198 aio_error():
199     for request 1 (descriptor 4): In progress
200 \fBx\fP
201 I/O completion signal received
202 aio_error():
203     for request 1 (descriptor 4): I/O succeeded
204 All I/O requests completed
205 aio_return():
206     for request 0 (descriptor 3): 4
207     for request 1 (descriptor 4): 2
208 .fi
209 .in
210 .SS プログラムのソース
211 \&
212 .nf
213 #include <stdlib.h>
214 #include <unistd.h>
215 #include <stdio.h>
216 #include <errno.h>
217 #include <aio.h>
218 #include <signal.h>
219
220 #define BUF_SIZE 20     /* Size of buffers for read operations */
221
222 #define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); } while (0)
223
224 #define errMsg(msg)  do { perror(msg); } while (0)
225
226 struct ioRequest {      /* Application\-defined structure for tracking
227                            I/O requests */
228     int           reqNum;
229     int           status;
230     struct aiocb *aiocbp;
231 };
232
233 static volatile sig_atomic_t gotSIGQUIT = 0;
234                         /* On delivery of SIGQUIT, we attempt to
235                            cancel all outstanding I/O requests */
236
237 static void             /* Handler for SIGQUIT */
238 quitHandler(int sig)
239 {
240     gotSIGQUIT = 1;
241 }
242
243 #define IO_SIGNAL SIGUSR1   /* Signal used to notify I/O completion */
244
245 static void                 /* Handler for I/O completion signal */
246 aioSigHandler(int sig, siginfo_t *si, void *ucontext)
247 {
248     write(STDOUT_FILENO, "I/O completion signal received\en", 31);
249
250     /* The corresponding ioRequest structure would be available as
251            struct ioRequest *ioReq = si\->si_value.sival_ptr;
252        and the file descriptor would then be available via
253            ioReq\->aiocbp\->aio_fildes */
254 }
255
256 int
257 main(int argc, char *argv[])
258 {
259     struct ioRequest *ioList;
260     struct aiocb *aiocbList;
261     struct sigaction sa;
262     int s, j;
263     int numReqs;        /* Total number of queued I/O requests */
264     int openReqs;       /* Number of I/O requests still in progress */
265
266     if (argc < 2) {
267         fprintf(stderr, "Usage: %s <pathname> <pathname>...\en",
268                 argv[0]);
269         exit(EXIT_FAILURE);
270     }
271
272     numReqs = argc \- 1;
273
274     /* Allocate our arrays */
275
276     ioList = calloc(numReqs, sizeof(struct ioRequest));
277     if (ioList == NULL)
278         errExit("calloc");
279
280     aiocbList = calloc(numReqs, sizeof(struct aiocb));
281     if (aiocbList == NULL)
282         errExit("calloc");
283
284     /* Establish handlers for SIGQUIT and the I/O completion signal */
285
286     sa.sa_flags = SA_RESTART;
287     sigemptyset(&sa.sa_mask);
288
289     sa.sa_handler = quitHandler;
290     if (sigaction(SIGQUIT, &sa, NULL) == \-1)
291         errExit("sigaction");
292
293     sa.sa_flags = SA_RESTART | SA_SIGINFO;
294     sa.sa_sigaction = aioSigHandler;
295     if (sigaction(IO_SIGNAL, &sa, NULL) == \-1)
296         errExit("sigaction");
297
298     /* Open each file specified on the command line, and queue
299        a read request on the resulting file descriptor */
300
301     for (j = 0; j < numReqs; j++) {
302         ioList[j].reqNum = j;
303         ioList[j].status = EINPROGRESS;
304         ioList[j].aiocbp = &aiocbList[j];
305
306         ioList[j].aiocbp\->aio_fildes = open(argv[j + 1], O_RDONLY);
307         if (ioList[j].aiocbp\->aio_fildes == \-1)
308             errExit("open");
309         printf("opened %s on descriptor %d\en", argv[j + 1],
310                 ioList[j].aiocbp\->aio_fildes);
311
312         ioList[j].aiocbp\->aio_buf = malloc(BUF_SIZE);
313         if (ioList[j].aiocbp\->aio_buf == NULL)
314             errExit("malloc");
315
316         ioList[j].aiocbp\->aio_nbytes = BUF_SIZE;
317         ioList[j].aiocbp\->aio_reqprio = 0;
318         ioList[j].aiocbp\->aio_offset = 0;
319         ioList[j].aiocbp\->aio_sigevent.sigev_notify = SIGEV_SIGNAL;
320         ioList[j].aiocbp\->aio_sigevent.sigev_signo = IO_SIGNAL;
321         ioList[j].aiocbp\->aio_sigevent.sigev_value.sival_ptr =
322                                 &ioList[j];
323
324         s = aio_read(ioList[j].aiocbp);
325         if (s == \-1)
326             errExit("aio_read");
327     }
328
329     openReqs = numReqs;
330
331     /* Loop, monitoring status of I/O requests */
332
333     while (openReqs > 0) {
334         sleep(3);       /* Delay between each monitoring step */
335
336         if (gotSIGQUIT) {
337
338             /* On receipt of SIGQUIT, attempt to cancel each of the
339                outstanding I/O requests, and display status returned
340                from the cancellation requests */
341
342             printf("got SIGQUIT; canceling I/O requests: \en");
343
344             for (j = 0; j < numReqs; j++) {
345                 if (ioList[j].status == EINPROGRESS) {
346                     printf("    Request %d on descriptor %d:", j,
347                             ioList[j].aiocbp\->aio_fildes);
348                     s = aio_cancel(ioList[j].aiocbp\->aio_fildes,
349                             ioList[j].aiocbp);
350                     if (s == AIO_CANCELED)
351                         printf("I/O canceled\en");
352                     else if (s == AIO_NOTCANCELED)
353                             printf("I/O not canceled\en");
354                     else if (s == AIO_ALLDONE)
355                         printf("I/O all done\en");
356                     else
357                         errMsg("aio_cancel");
358                 }
359             }
360
361             gotSIGQUIT = 0;
362         }
363
364         /* Check the status of each I/O request that is still
365            in progress */
366
367         printf("aio_error():\en");
368         for (j = 0; j < numReqs; j++) {
369             if (ioList[j].status == EINPROGRESS) {
370                 printf("    for request %d (descriptor %d): ",
371                         j, ioList[j].aiocbp\->aio_fildes);
372                 ioList[j].status = aio_error(ioList[j].aiocbp);
373
374                 switch (ioList[j].status) {
375                 case 0:
376                     printf("I/O succeeded\en");
377                     break;
378                 case EINPROGRESS:
379                     printf("In progress\en");
380                     break;
381                 case ECANCELED:
382                     printf("Canceled\en");
383                     break;
384                 default:
385                     errMsg("aio_error");
386                     break;
387                 }
388
389                 if (ioList[j].status != EINPROGRESS)
390                     openReqs\-\-;
391             }
392         }
393     }
394
395     printf("All I/O requests completed\en");
396
397     /* Check status return of all I/O requests */
398
399     printf("aio_return():\en");
400     for (j = 0; j < numReqs; j++) {
401         ssize_t s;
402
403         s = aio_return(ioList[j].aiocbp);
404         printf("    for request %d (descriptor %d): %ld\en",
405                 j, ioList[j].aiocbp\->aio_fildes, (long) s);
406     }
407
408     exit(EXIT_SUCCESS);
409 }
410 .fi
411 .SH 関連項目
412 .ad l
413 .nh
414 \fBio_cancel\fP(2), \fBio_destroy\fP(2), \fBio_getevents\fP(2), \fBio_setup\fP(2),
415 \fBio_submit\fP(2), \fBaio_cancel\fP(3), \fBaio_error\fP(3), \fBaio_init\fP(3),
416 \fBaio_read\fP(3), \fBaio_return\fP(3), \fBaio_write\fP(3), \fBlio_listio\fP(3)
417
418 .UR http://www.squid\-cache.org\:/~adrian\:/Reprint\-Pulavarty\-OLS2003.pdf
419 .UE
420 .SH この文書について
421 この man ページは Linux \fIman\-pages\fP プロジェクトのリリース 3.50 の一部
422 である。プロジェクトの説明とバグ報告に関する情報は
423 http://www.kernel.org/doc/man\-pages/ に書かれている。