OSDN Git Service

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