6

aio_read/write に関するドキュメントによると、AIO ライブラリが非同期ファイル I/O 操作が完了したことをアプリケーションに通知する方法は基本的に 2 つあります。1) シグナルを使用できる、2) コールバック関数を使用できる

コールバック関数はシグナルよりもはるかに優れており、おそらく高レベルのマルチスレッド ライブラリに統合する方がはるかに簡単だと思います。残念ながら、この機能のドキュメントは控えめに言ってもめちゃくちゃです。sigevent 構造体のマニュアル ページなどの一部の情報源は、sigevent 構造体の sigev_notify データ メンバーを SIGEV_CALLBACK に設定してから、関数ハンドラーを提供する必要があることを示しています。おそらく、ハンドラーは同じスレッドで呼び出されます。他のドキュメントでは、sigev_notify を SIGEV_THREAD に設定する必要があることが示されています。これにより、新しく作成されたスレッドでコールバック ハンドラが呼び出されます。

いずれにせよ、私の Linux システム (カーネル 2.6.28 の Ubuntu) では、SIGEV_CALLBACK はどこにも定義されていないようですが、SIGEV_THREAD は宣伝どおりに機能します。残念ながら、コールバック ハンドラーを呼び出すために新しいスレッドを作成するのは、特に多くのハンドラーを呼び出す必要がある場合、非常に効率が悪いようです。ほとんどのネットワーク I/O イベント デマルチプレクサが動作する方法と同様に、既存のスレッド プールを使用することをお勧めします。QNX などの UNIX の一部のバージョンには SIGEV_SIGNAL_THREAD フラグが含まれており、指定された既存のスレッドを使用してハンドラーを呼び出すことができますが、これは Linux では使用できないようであり、POSIX の一部でさえないようです。標準。

それで、ハンドラーが呼び出されるたびに新しいスレッドを作成/破棄するのではなく、事前に割り当てられたバックグラウンドスレッド/スレッドプールでユーザーハンドラーを呼び出す方法で POSIX AIO ライブラリを使用することは可能ですか?

4

4 に答える 4

2

通常、専用のバックグラウンド スレッドで通常の IO を実行し、完了コールバックを好きなようにディスパッチすることで、非同期 IO をシミュレートする方が簡単で移植性が高いと思います。

于 2009-11-05T23:54:05.350 に答える
1

1 つの方法はSIGEV_SIGNALリアルタイム シグナルで を使用して、準備完了ファイル記述子をシグナル ハンドラに「運ぶ」ことです。リアルタイム シグナル キューとシグナル ハンドラーは 1 つのスレッドで非同期に実行されるため、このアプローチは機能的に以下とほぼ同等SIGEV_CALLBACKです。

/*
 * Warning!  Untested!
 * Also, safe initialization, per-thread signal masking and
 * error-checking omitted.
 */

static void my_callback(int sig, siginfo_t *info, void *context) {
  int fd;

  fd = info->si_value.sival_int;
  /* ...enqueue the fd for processing... */
}

struct sigaction sa;

sa.sa_handler = my_callback;                 /* Register our async callback */
sa.sa_flags = SA_SIGINFO;
sigaction(SIGRTMIN+1, &sa, NULL);
...

struct aiocb ac;

ac.aio_filedes = some_fd;
ac.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
ac.aio_sigevent.sigev_signo  = SIGRTMIN+1;   /* Associate callback w. aiocb */
....
aio_read(&ac);

これで、my_callbackが 1 つのスレッドで非同期に起動されます。fdをヘルパー スレッドプールに渡すのはあなた次第です。利用できない場合にフォールバックする方法を示す、この少しの SGI コードも参照してください。SIGEV_SIGNALSIGEV_CALLBACK

于 2009-08-05T21:17:25.773 に答える
0

完了呼び出しごとに複数のスレッドが作成/破棄されることを心配している場合は、IOをバッチ処理しないのはなぜですか?

listioapisを使用します。

struct aiocb **myaiocb;
 [just an array of aiocb pointers, where each aiocb points to an IO buffer
  and the operation to be performed, etc]
....
lio_listio(LIO_NOWAIT, myaiocb, num_ios, &sigevent);

リストIOの利点は、リスト内のすべてのIOが完了した後(成功/失敗)にのみコールバックハンドラーが呼び出されることです。aio_returnを使用して、各IO操作のステータスを確認できます。

于 2010-12-01T17:56:23.517 に答える
0

これは非常に古いスレッドですが、同じ問題を調べているときに Google のトップに表示されました。現在、aio_initaio が使用するスレッドの最大数とそれらのスレッドの寿命を指定できる GNU 拡張機能があります。

于 2016-02-18T17:30:49.177 に答える