web-dev-qa-db-ja.com

Cライブラリで非ブロッキングIO APIを提供する

プロセス間通信用のCライブラリ( SlipRock )に取り組んでいます。

ライブラリは現在、単純なブロッキングAPIを公開しています。これは使いやすく、誤用を(比較的)難しくします(結局これはCです)。Windowsポート(基本的に共通のコードを共有しない)の実装に取り​​掛かると、クロスプラットフォームの実装は(比較的)簡単になります。 。

ただし、ブロッキングAPIが特定のユースケースで問題を引き起こす可能性があることを心配しています。それにもかかわらず、私は使いやすいノンブロッキングAPIを提供することを非常に心配しており、libuvやlibeventのような重いライブラリを使用する必要はありません

自然に疑似ブロックを行う(緑色のスレッドをブロックする)言語へのバインディングIO(Go、Erlang、GHC Haskellなど)は、常により高いレベルのAPI(または全体プロトコル–それは高水準言語ではそれ複雑ではありません)同様に、プロトコルの一部ではないプロトコルを実装することが可能です高級言語でのネイチャーブロッキング(名前付きパイプ/ AF_UNIXソケットのリッスンとAF_UNIXソケットへの接続、および以下のパスワード交換)。

ノンブロッキングC APIを提供する必要がありますか、またはバインディングがAPIの基礎として使用する必要がある2つまたは3つの関数を提供する必要がありますか?

ノンブロッキングAPIの実装について私が考えていた方法は、ユーザーが手動で呼び出す必要のあるステートマシンを用意することでした。しかし、そのためには、ユーザーが基になるIOハンドルにアクセスする必要があります。これは、意図した戻り値です!したがって、公開したい場合は、カプセル化を解除するか、イベントループ実装に結び付ける必要があります。パフォーマンスはそれほど重要ではないこのコード用の非同期API。

4
Demi

低レベルのオペレーティングシステム固有のフックを提供して、非ブロッキングIOを有効(または促進)することもできます。

たとえば、LinuxおよびPOSIXシステムの場合、アクティブなファイル記述子セットを取得する方法を提供できます(そして、ユーザーにそれらの poll(2) を呼び出させ、おそらくユーザーにいくつかのフックを提供します) pollが利用可能なIOを検出したときの実際のI/O)、およびおそらくそのセットが変更されたときに通知されるようにします。 libcurlのマルチインターフェイス はインスピレーションを与える可能性があります(そしておそらく mq )。そして、あなたもターゲットにしようとするかもしれません aio(7)

おそらく、既存の event loop ライブラリー( libevent または libev など)の上にライブラリーを設計する可能性があります。

ライブラリの非同期の側面は常に扱いにくいため、賢明に文書化することを忘れないでください。マルチスレッドアプリケーションでの使用方法を文書化することもできます。

非ブロッキングAPIを提供する必要があるかどうかは、ユーザーのニーズによって異なります。ユーザーにヘビーウェイトライブラリへの依存関係の追加を強いることは悪い考えであることに同意します。ノンブロッキングAPIを別のライブラリに配置することもできます。

一方、カプセル化を解除する必要があることには同意しません。 APIの詳細はわかりませんが、何らかの方法でファイルハンドルを非表示にできると思います。

ライブラリの実際のユーザーに何が必要かを尋ねましたか?そうでない場合、なぜ非ブロッキングAPIを追加するのですか?

1
Frank Hileman

ノンブロッキングインターフェースを提供したい場合、それを行うにはいくつかの方法しかありません:

  1. イベントループにクライアントコードを埋め込みます。

    独自のイベントループ/ディスパッチャを提供します。クライアントが独自のソケット、タイムアウト、イベントコールバックを追加するためのインターフェースを追加します。

    イベントループを実行し、内部非同期状態を管理し、sliprock書き込みが完了したとき、またはselect/poll/whateverイベントが、ユーザーが登録したソケットで発生したときにクライアントコールバックを呼び出します

  2. Fdsをクライアントイベントループに公開します。

    内部fdsの1つに何かが発生した場合、クライアントにハンドラーの呼び出しを要求します。

ハイブリッドオプションは、ソケットと非同期状態を処理する専用スレッドで独自のイベントループを実行し、既存のイベントループでポーリングできる単一の公開されたsocketpairまたはeventfdを介してクライアントコードと通信します。

最初のオプションとハイブリッドオプションの両方で、クライアントがステートマシンを手動で呼び出す必要がなくなります。

1
Useless