システムインタフェース

高性能入出力

この節では、実時間プロセスでの入出力について説明します。SunOS 5.0 から 5.8 では、高速で非同期の入出力操作を実行するための 2 種類のインタフェースをライブラリで提供しています。POSIX 非同期入出力インタフェースは新しい標準です。堅牢性向上のため、SunOS は情報の消失やデータの不一致を防止するためのファイルおよびメモリ内同期操作とモードも提供しています。

標準の UNIX 入出力は、アプリケーションのプログラマと同期します。read(2) または write(2) を呼び出すアプリケーションは、通常はシステムコールが終了するまで待ちます。

実時間アプリケーションは、入出力に非同期で結合された特性を必要とします。非同期入出力呼び出しを発行したプロセスは、入出力操作の完了を待たずに先に進むことができます。呼び出し側は、入出力操作が終了すると通知されます。その間、プロセスは他の動作を行います。

非同期入出力は、任意の SunOS ファイルで使用できます。ファイルは同期して開かれますが、特別なフラグ設定は必要ありません。非同期入出力転送には、呼び出し、要求、操作の 3 つの要素があります。アプリケーションは非同期入出力関数を呼び出し、入出力要求が待ち行列に置かれ、呼び出しはただちに復帰します。ある時点で、システムは要求を待ち行列から取り出し、入出力操作を開始します。

非同期入出力要求と標準入出力要求は、任意のファイル記述子で混在させることができます。システムは、読み取り要求と書き込み要求の特定の順序を維持しません。システムは、保留状態にあるすべての読み取り要求と書き込み要求の順序を任意に並べ替えます。特定の順序を必要とするアプリケーションは、前の操作の完了を確認してから従属する要求を発行しなければなりません。

POSIX 非同期入出力

POSIX 非同期入出力は、aiocb 構造体を使用して行います。aiocb 制御ブロッキングは、各非同期入出力要求を識別し、すべての制御情報を持っています。制御ブロッキングは、一度に 1 つの要求だけに使用でき、その要求が完了すると再使用できます。

一般的な POSIX 非同期入出力操作は、aio_read(3RT) または aio_write(3RT) 呼び出しによって開始します。ポーリングまたはシグナルを使用して、操作の完了を判断できます。シグナルを操作の完了に使用する場合は、各操作に一意にタグを付けることができます。タグは生成されたシグナルの si_value 構成要素に戻されます (詳細は、siginfo(3HEAD) のマニュアルページを参照してください)。

aio_read(3RT)

aio_read(3RT) は、読み取り操作の開始のために非同期入出力制御ブロッキングを使用して呼び出します。

aio_write(3RT)

aio_write(3RT) は、書き込み操作の開始のために非同期入出力制御ブロッキングを指定して呼び出します。

aio_return(3RT)aio_error(3RT)

aio_return(3RT)aio_error(3RT)は、操作が完了しているとわかった後、それぞれ戻り値とエラー値を取得するために呼び出します。

aio_cancel(3RT)

aio_cancel(3RT) は、保留状態の操作を取り消すために非同期入出力制御ブロッキングを指定して呼び出します。

aio_fsync(3RT)

aio_fsync(3RT) は、指定したファイルで保留状態のすべての入出力操作に対する非同期の fsync(3C) または fdatasync(3RT) 要求を待ち行列に並べます。

aio_suspend(3RT)

aio_suspend(3RT) は、1 つ以上の先行する非同期入出力要求が同期して行われるかのように呼び出し側を一時停止します。

Solaris 非同期入出力

通知 (SIGIO)

非同期入出力呼び出しが正常に復帰しても、入出力操作は待ち行列に並べられただけであり、実行を待っています。実際の操作は、戻り値と潜在的なエラー識別子も持っています。これらの値は、同期呼び出しの結果として呼び出し側に戻されます。入出力が終了すると、戻り値とエラー値は、要求時点でユーザが aio_result_t へのポインタとして指定した位置に格納されます。aio_result_t 構造体は、<sys/asynch.h> に次のように定義されています。


typedef struct aio_result_t {
 	ssize_t	aio_return; /* 読み取りまたは書き込みの戻り値 */
 	int 		aio_errno;  /* 入出力によって生成されたエラー番号 */
 } aio_result_t;

aio_result_t が変更されると、入出力要求を行なったプロセスに SIGIO シグナルが配信されます。

2 つ以上の非同期入出力操作を保留状態にしている場合、どの要求によって SIGIO シグナルが生じたか、またはどちらの要求によって SIGIO シグナルが生じたのかは調べることはできません。SIGIO を受け取ったプロセスは、SIGIO を生じた原因となる条件をすべてチェックしなければなりません。

aioread(3AIO)

aioread(3AIO)read(2) の非同期版です。aioread(3AIO) は通常の読み取り引数に加えて、ファイル位置と、システムが操作結果を格納する aio_result_t 構造体のアドレスを指定する引数を取ります。ファイル位置には、操作前にファイル内で行うシークを指定します。aioread(3AIO) 呼び出しが成功したか失敗したかに関係なく、ファイルポインタが更新されます。

aiowrite(3AIO)

aiowrite(3AIO) 関数は write(2) の非同期版です。aiowrite(3AIO) は通常の書き込み引数以外にファイル位置と、操作結果が格納される aio_result_t 構造体のアドレスを指定する引数を取ります。

ファイル位置には、操作の前にファイル内で行うシークを指定します。aiowrite(3AIO) 呼び出しが成功すると、ファイルポインタはシークと書き込みが成功した場合の位置に変更されます。ファイルポインタは書き込みを行なった後、以降の書き込みができなくなった場合も変更されます。

aiocancel(3AIO)

aiocancel(3AIO) は、その aio_result_t 構造体を引数として指定した非同期要求の取り消しを試みます。aiocancel(3AIO) 呼び出しは、要求がまだ待ち行列にある場合だけに成功します。操作がすでに進行していると aiocancel(3AIO) は失敗します。

aiowait(3AIO)

aiowait(3AIO) を呼び出すと、少なくとも 1 つの未処理の非同期入出力操作が完了するまで呼び出しプロセスはブロッキングされます。タイムアウトパラメタは、入出力の完了を待つ最大インタバルを指します。0 のタイムアウト値は、待つ必要がないことを指定します。aiowait(3AIO) は、完了した操作の aio_result_t 構造体へのポインタを戻します。

poll(2)

非同期の入出力イベントの完了を、SIGIO 割り込みに依存するのではなく同期的に決定するには、poll(2) を使用してください。SIGIO 割り込みの原因を調べるためにポーリングすることもできます。

poll(2) をあまり多くのファイルで使用すると、処理が遅くなります。この問題は、poll(7D) で解決します。

poll(7D)

/dev/poll によって、多数のファイル記述子のポーリングを非常にスケーラブルに行うことができます。これは、新しい API のセットと新しいドライバである /dev/poll によって可能になっています。/dev/poll API は poll(2) の代替ではなく、選択して使用するものです。poll(7D)/dev/poll API の詳細と例を示しています。適切に使用すると、/dev/poll API は poll(2) よりも適切にスケールが行われます。特に次の条件を満たすアプリケーションに適します。

close(2)

ファイルは、close(2) 呼び出しによって閉じられます。close(2) を呼び出すと、取り消すことができる未処理の非同期入出力要求はすべて取り消されます。close(2) 関数は、取り消せない操作の完了を待ちます (詳細は、aiocancel(3AIO)を参照してください)。close(2) 呼び出しが戻ると、そのファイル記述子について保留状態にある非同期入出力要求はなくなります。ファイルが閉じられると、取り消されるのは指定したファイル記述子に対する待ち行列内にある非同期入出力要求だけです。他のファイル記述子について、保留状態にある入出力要求は取り消されません。

同期入出力

アプリケーションは、情報が安定した記憶領域に書き込まれたことや、ファイル変更が特定の順序で行われることを保証する必要がある場合があります。同期入出力は、このような場合のために用意されています。

同期のモード

SunOS 5.0 から 5.8 では、物理記憶領域媒体でエラーなしに読み取れることがシステムで保証されている場合、書き込まれたデータがすべて、そのファイルをあとで開いた際に (システムや電源の障害後であっても)、書き込み操作のために通常ファイルへ正しく転送されます。物理記憶領域媒体上のデータのイメージを要求側のプロセスが利用できる場合、データは読み取り操作のために正しく転送されます。入出力操作は、関連づけられているデータが正しく転送されたか、操作が失敗と診断された場合に完了します。

入出力操作は、次の場合に同期入出力データの保全を完了します。

読み取りについては、操作は完了または失敗と診断されます。読み取りが完了するのは、データのイメージが要求側のプロセスに正しく転送された場合だけです。同期読み取り操作が要求された時点で、読み取るデータに影響を与える書き込み要求が保留状態にある場合は、データを読み取る前に書き込み要求が正しく転送されます。

書き込みについては、操作は完了または失敗と診断されます。書き込みが完了するのは、書き込み要求で指定されたデータが正しく転送され、そのデータを取り出すために必要なファイルシステム情報がすべて正しく転送された場合だけです。

データの取り出しに必要のないファイル属性 (アクセス時間、変更時間、状態変更時間) は、呼び出し側プロセスに戻る前に正しく転送されているわけではありません。

同期入出力ファイルの保全の完了は、呼び出し側プロセスに戻る前に入出力操作に関連するすべてのファイル属性 (アクセス時間、修正時間、状態変更時間を含む) が正しく転送されなければならない点を除けば、同期入出力データの保全の完了と同じです。

ファイルの同期

fsync(3C) 関数と fdatasync(3RT) 関数は、ファイルを二次記憶領域と明示的に同期をとります。形式は次のようになります。

fsync(3C) は、入出力ファイルの保全完了レベルで関数の同期をとることを保証し、fdatasync(3RT) は、入出力データの保全完了レベルで関数の同期をとることを保証します。

アプリケーションは、操作が完了する前に各入出力操作の同期をとるように指定できます。open(2) または fcntl(2) によってファイル記述に O_DSYNC フラグを設定すると、操作が完了したと見なされる前にすべての入出力書き込み (write(2)aiowrite(3AIO)) が入出力データ完了に達します。ファイル記述に O_SYNC フラグを設定すると、操作が完了したと見なされる前に、すべての入出力書き込みが入出力ファイル完了に達します。ファイル記述に O_RSYNC フラグを設定すると、すべての入出力読み取り (read(2)aio_read(3RT)) が、O_DSYNC または O_SYNC を記述子に設定した書き込み要求と同じ完了レベルに達します。