質問

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

知りたいのは:

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

私が利用できる他の多重化メカニズムは完璧に優れていますが、そこら中に飛び交うランダムな情報の断片に興味が湧きました。

役に立ちましたか?

解決

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

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

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

したがって、最終的には POSIX AIO はサービスを提供しない状態になります。 どれでも 有用な目的。使用しないでください。

他のヒント

ソケット I/O を効率的に実行することは、kqueue、epoll、IO 完了ポートなどによって解決されています。非同期ファイル I/O の実行は、ある意味後発の技術です (Windows のオーバーラップ I/O と Solaris の初期の posix AIO サポートは別として)。

ソケット I/O を実行したい場合は、おそらく上記のメカニズムのいずれかを使用した方がよいでしょう。

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

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

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

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

とはいえ、posix AIO のインターフェイスは非常に扱いにくいです。たとえば、次のとおりです。

  • イベント コールバックの効率的で十分にサポートされている唯一の手段はシグナル経由です。これは、プロセス グローバル シグナル名前空間からのシグナル番号を使用することになるため、ライブラリでの使用が困難になります。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 プラットフォーム (Linux、BSD、Solaris、AIX、tru64) が posix AIO をサポートしています。Windows は、重複したファイル I/O を介してこれをサポートします。私の理解では、実際に非同期をサポートしているのは Solaris、Windows、Linux だけです。ファイル I/O はドライバーに至るまで行われますが、他の OS は非同期をエミュレートします。カーネル スレッドによる I/O。Linux は例外で、glibc での posix AIO 実装は、ユーザー レベルのスレッドで非同期操作をエミュレートしますが、そのネイティブの非同期 I/O インターフェイス (io_submit() など) は、ドライバーがサポートしていると仮定すると、ドライバーに至るまで完全に非同期です。 。

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

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

aio_write があります - glibc に実装されています。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 の違いは?

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top