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


93

POSIX AIOファシリティをさまざまな詳細で説明するページがWebに散在しています。それらのどれもひどく最近です。彼らが何を説明しているのか、正確には明確ではありません。たとえば、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」を本当にサポートしている人はいますか?

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

回答:


27

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

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

バッファリングされていない直接I / Oは、トランザクションデータベースでのみ有用であり、ディスクI / Oを管理するために独自のスレッドまたはプロセスを作成する傾向があります。

だから、サービス提供ではないの位置にPOSIX AIOを離れる最後に任意の有用な目的を。使用しないでください。


8
ネットワーク(NFS、Samba)ファイルシステムからの読み取り/書き込みについてはどうですか?
Alex B

1
上手。私はいくつかの大きなダムライターを持っていますが、それらをキャッシュに移動させると、ピーク時にdirty_ratioにヒットし、他のすべてのユーザーをブロックします。それらに直接IOを使用するだけでは、非常に遅くなります。スレッドが1つしかない場合、自分で管理できますが、1つのトレッドでさまざまなIO優先度をサポートするのは困難です。AIOが機能していれば、AIO + CFQは本当に良い組み合わせに見えます
n-alexander

37
同意しません。ディスクI / Oはバッファリングされる傾向がありますが、ブロッキングになる可能性があります。ファイルFDをpoll()するとき、それがブロックする場合でも、FDが読み取り可能であることを常に報告します。これにより、スレッドまたはAIOを使用しない限り、イベント形式でディスクファイルに対して非ブロッキング操作を実行することができなくなります。
Hongli

2
@マット:データグラムソケットでは順序は重要ではありません。@Zan:非同期I / Oは、リアルタイムストリーミングデータ(メディアプレーヤーなど)の事前バッファリングに非常に適しています。
Ben Voigt

13
イベントベースのシステムではAIOが役に立たないというのは本当ではありません。実際には、適切なAIOを使用してゼロコピーネットワーキングを実現できますが、recv()へのイベントベースの通知では不可能です。他のものは、これをほとんど理論上の制限にするために共謀するかもしれませんが、適切なAIOの欠如(WindowsでのOVERLAPPED)は、Linuxの最後の大きな穴の1つだと思います。
Jon Watte、2012年

69

ソケットI / Oを効率的に行うことは、kqueue、epoll、IO完了ポートなどで解決されました。非同期ファイルI / Oの実行は、後発的なものです(WindowsのオーバーラップI / Oとposix AIOのソラリス初期サポートは別として)。

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

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

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

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

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

とは言っても、posix AIOは非常に扱いにくいインターフェースを持っています。例えば:

  • イベントコールバックの唯一の効率的で十分にサポートされている手段は、シグナルを経由することです。これは、プロセスグローバルシグナル名前空間からのシグナル番号を使用することを意味するため、ライブラリでの使用を困難にします。お使いのOSがリアルタイム信号をサポートしていない場合は、未処理の要求をすべてループして、実際に終了した要求を特定する必要があることも意味します(これは、たとえばLinuxではなくMac OS Xの場合です)。マルチスレッド環境でシグナルをキャッチすると、いくつかのトリッキーな制限も発生します。通常、シグナルハンドラー内のイベントに反応することはできませんが、シグナルを発生させるか、パイプに書き込むか、またはLinuxでsignalfd()を使用する必要があります。
  • 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のみが本当に非同期をサポートしています。他のOSは非同期をエミュレートするのに対し、ファイルI / Oはドライバーまで続きます。カーネルスレッドによるI / O。Linuxは例外ですが、glibcのposix AIO実装はユーザーレベルのスレッドで非同期操作をエミュレートしますが、ネイティブの非同期I / Oインターフェイス(io_submit()など)は、ドライバーがサポートしていると仮定して、ドライバーまで完全に非同期です。

私は、どのfdについてもposix AIOをサポートせず、通常のファイルに制限することがOSの間でかなり一般的であると信じています。


Win32が最初にリリースされて以来、WindowsにはOVERLAPPED I / Oサポートディスクファイルがありました。それはまったく新しいものではありません。そしてPOSIXでは、シグナルの名前空間はプロセス全体ではなく、スレッドごとです。シグナルは特定のスレッドに配信されます(またはaioはその例外ですが、確実に思い出せませんか?)。
Ben Voigt、2011年

1
AIOがシグナルを配信するスレッドを指定する方法はありません。Linuxでは、ほとんどの場合、それはaio _ *()コマンドを発行したスレッドに配信されるようですが、常にではありません(これに対して私が見つけた唯一の解決策は、複数のsignalfdを作成することでした)。数年前のカーネルメーリングリストには、これを追加するLinuxパッチがありましたが、それは実装されておらず、POSIXの拡張機能でした。Mac OS Xでは、シグナルは主に(私の経験では)メインスレッドに配信されるようです。私はPOSIXが特定の動作を必要とするとは思わない、もしそうなら、仕様の一部を見たいと思う。
Arvid、2011年

5
glibcのaio_read / writeの実装はユーザーランドでスレッドを使用するため、ここではカーネルスレッドも使用されません。
Marenz

「常に」とはどういう意味ですか?書き込みは、任意の方法で、またはAIOを使用するときにカーネルによってキャッシュされますか?書き込みが正常に完了したことをソフトウェアに確認させる方法がなければならないようです。そうしないと、整合性とトランザクションの目標を達成できません。
MikeB 2013年

AIOを使用できるもう1つのライブの例はnginxです。すべてのモードがサポートされています。ユーザーランドスレッドへのオフロードを好む場合、通常はダイレクトIOよりもはるかに悪いことがわかりますが、LinuxネイティブAIOはダイレクトIOと同等です。AIOが実質的に有益である状況は、ページキャッシュの負荷が非常に高いことです。非同期IOと直接IOの概念的な違いは、ftp.dei.uc.pt / pub / linux / kernel / people / suparna / aio
wick


2

aio_writeがあります-glibcに実装されています。aio_readまたはaio_write関数の最初の呼び出しは、そのスレッドへの多数のユーザーモードスレッド、aio_writeまたはaio_read post要求を生成し、スレッドは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の違いは?


の欠陥の多くは、aio_write上記のstackoverflow.com/a/5307557/13564
Glyph
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.