96

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

知りたい:

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

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

4

4 に答える 4

72

ソケットI/Oを効率的に実行することは、kqueue、epoll、IO完了ポートなどで解決されました。非同期ファイルI/Oを実行することは、一種の遅刻です(WindowsのオーバーラップI / OとsolarisによるposixAIOの早期サポートは別として)。

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

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

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

ただし、読み取り操作の場合、カーネルに読み取りの優先順位付けと順序付けを行わせる場合は、実際にはAIOが唯一のオプションです。これが、カーネルが(理論的に)どのユーザーレベルのアプリケーションよりも優れている理由です。

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

とは言うものの、posixAIOのインターフェースは非常に扱いにくいものです。たとえば次のようになります。

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

posix AIOを使用した実際のアプリケーションについては、lighttpd(lighty)を見ることができます。これは、サポートを導入するときにパフォーマンス測定値も投稿しました。

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

OS間では、どのfdでもposix AIOをサポートしないのはかなり一般的だと思いますが、通常のファイルに制限します。

于 2011-03-15T04:30:59.297 に答える
30

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

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

バッファなしのダイレクト I/O は、トランザクション データベースでのみ実際に役立ちます。トランザクション データベースは、ディスク I/O を管理するために独自のスレッドまたはプロセスを作成する傾向があります。

したがって、最終的には、POSIX AIO は有用な目的を果たさない立場に置かれます。使用しないでください。

于 2008-09-17T23:15:51.280 に答える
12

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

于 2012-10-26T15:29:36.813 に答える