web-dev-qa-db-ja.com

POSIX非同期I / O(AIO)のステータスは何ですか?

POSIX AIO機能をさまざまな詳細度で説明するページがWebのあちこちに散らばっています。それらのどれもひどく最近のものではありません。彼らが何を正確に説明しているかは明確ではありません。たとえば、「公式」(?) Linuxカーネルの非同期I/OサポートのWebサイト は、ソケットが機能しないことを示していますが、Ubuntu 8.04の「aio.h」のマニュアルページです。 1つのワークステーションはすべて、任意のファイル記述子で機能することを意味するようです。次に、 ライブラリレイヤーで動作しているように見える別のプロジェクト さらに少ないドキュメントがあります。

知りたい:

  • POSIX AIOの目的は何ですか?私が見つけることができる実装の最も明白な例は、ソケットをサポートしていないと言うことを考えると、全体が私には奇妙に思えます。非同期ディスクI/O専用ですか?もしそうなら、なぜハイパー汎用APIなのでしょうか?そうでない場合、なぜディスクI/Oが最初に攻撃されたのですか?
  • どこに例がありますかcomplete見ることができるPOSIX AIOプログラム?
  • 誰かが実際にそれを実際に使用していますか?
  • POSIX AIOをサポートするプラットフォームは何ですか?それらのどの部分をサポートしていますか? <aio.h>が約束していると思われる暗黙の「任意のFDへのI/O」を本当にサポートしている人はいますか?

私が利用できる他の多重化メカニズムは完全に優れていますが、そこに散らばっている情報のランダムな断片は、私を興味津々にしました。

93
Glyph

ネットワークI/OはAIOの優先事項ではありません。POSIXネットワークサーバーを作成するすべての人が、イベントベースのノンブロッキングアプローチを使用しているためです。古いスタイルのJava「10億のブロッキングスレッド」アプローチはひどくひどいものです。

ディスク書き込みI/Oはすでにバッファリングされており、posix_fadviseなどの関数を使用してディスク読み取りI/Oをバッファにプリフェッチできます。そのため、AIOの唯一の有用な目的として、バッファなしの直接ディスクI/Oが残ります。

直接のバッファなしI/Oは、トランザクションデータベースにのみ本当に役立ち、ディスクI/Oを管理する独自のスレッドまたはプロセスを記述する傾向があります。

そのため、最後にPOSIX AIOを役に立たない位置に置きますany有用な目的。使用しないでください。

25
Zan Lynx

ソケットI/Oの効率的な実行は、kqueue、epoll、IO完了ポートなどで解決されました。非同期ファイルI/Oの実行は、ウィンドウの重複したI/O Oおよびsolarisは、posix AIOを早期にサポートしています。

ソケットI/Oを実行する場合は、上記のメカニズムのいずれかを使用することをお勧めします。

したがって、AIOの主な目的は、非同期ディスクI/Oの問題を解決することです。これは、Mac OS Xがソケットではなく通常のファイルに対してのみAIOをサポートする理由である可能性が最も高くなります(kqueueの方が優れているため)。

通常、書き込み操作はカーネルによってキャッシュされ、後でフラッシュされます。たとえば、ドライブの読み取りヘッドが、ブロックが書き込まれる場所をたまたま通過した場合。

ただし、読み取り操作の場合、カーネルに読み取りの優先順位を付けて順序付けする場合は、AIOが本当に唯一のオプションです。 kernalが(理論的に)どのユーザーレベルのアプリケーションよりも優れているのかを次に示します。

  • カーネルは、アプリケーションのディスクジョブだけでなく、すべてのディスクI/Oを認識し、それらをグローバルレベルで注文できます。
  • カーネルは(おそらく)ディスク読み取りヘッドの場所を知っており、ヘッドを最短距離で移動するために、最適な順序で渡す読み取りジョブを選択できます。
  • カーネルは native command queuing を利用して、読み取り操作をさらに最適化できます
  • 特に、読み取りが(論理的に)連続していない場合は、lio_listio()を使用してシステムコールごとにreadv()よりも多くの読み取り操作を発行できるため、システムコールのオーバーヘッドがわずかに節約されます。
  • 読み取りまたは書き込み呼び出しでブロックするために余分なスレッドを必要としないため、AIOを使用するとプログラムが少し単純になる場合があります。

とはいえ、posix AIOには非常に厄介なインターフェイスがあります。たとえば:

  • イベントコールバックの唯一の効率的で十分にサポートされている手段は、プロセス経由のシグナル名前空間からのシグナル番号を使用することを意味するため、ライブラリでの使用を困難にするシグナル経由です。 OSがリアルタイムシグナルをサポートしていない場合、未処理のリクエストをすべてループして、実際に終了したリクエストを特定する必要があります(LinuxではなくMac OS Xの場合など)。マルチスレッド環境でシグナルをキャッチすると、いくつかの注意が必要な制限も生じます。通常、シグナルハンドラー内のイベントに反応することはできませんが、シグナルを発生させるか、パイプに書き込むか、signalfd()を使用する必要があります(Linuxの場合)。
  • lio_suspend()にはselect()と同じ問題がありますが、ジョブの数に応じて拡張性があまりありません。
  • lio_listio()は、実装されているように、渡すことができるジョブの数がかなり制限されており、移植可能な方法でこの制限を見つけることは簡単ではありません。 sysconf(_SC_AIO_LISTIO_MAX)を呼び出す必要がありますが、これは失敗する可能性があります。その場合、AIO_LISTIO_MAX定義を使用できますが、これは必ずしも定義されているわけではありません。

Posix AIOを使用した実際のアプリケーションについては、lighttpd(lighty)をご覧ください。サポートを導入する際に パフォーマンス測定 も投稿されています。

現在、ほとんどのposixプラットフォームはposix AIOをサポートしています(Linux、BSD、Solaris、AIX、tru64)。 Windowsは、重複したファイルI/Oを介してサポートします。私の理解では、Solaris、Windows、Linuxのみが非同期を本当にサポートしています。他のOSは非同期をエミュレートしますが、ファイルI/Oはドライバーまでずっと続きます。カーネルスレッドを使用したI/O。 Linuxは例外であり、glibcのposix AIO実装はユーザーレベルのスレッドで非同期操作をエミュレートしますが、ネイティブの非同期I/Oインターフェース(io_submit()など)は、ドライバーがサポートすることを前提として、ドライバーまで完全に非同期です。 。

OSでは、fdに対してposix AIOをサポートせず、通常のファイルに制限することはかなり一般的だと思います。

69
Arvid

Libtorrent開発者はこれに関するレポートを提供します: http://blog.libtorrent.org/2012/10/asynchronous-disk-io/

11
Allen

Glibcに実装されたaio_writeがあります。 aio_readまたはaio_write関数の最初の呼び出しは、多数のユーザーモードスレッド、そのスレッドへのaio_writeまたはaio_readポスト要求を生成します。スレッドはpread/pwriteを行い、完了するとブロックされた呼び出しスレッドに応答がポストバックされます。

また、カーネルレベルでサポートされている「本当の」aioです(そのためにはlibaioが必要です。io_submit呼び出し http://linux.die.net/man/2/io_submit を参照してください)。そのためにO_DIRECTも必要です(すべてのファイルシステムでサポートされているわけではありませんが、主要なファイルシステムではサポートされています)

こちらをご覧ください:

http://lse.sourceforge.net/io/aio.html

http://linux.die.net/man/2/io_submit

LinuxでのPOSIX AIOとlibaioの違い?

2
MichaelMoser