2012-03-22 9 views
3

私はカーネルレベルの非同期I/O(すなわち、libaio.h)で作業しています。 struct iocbio_submitで送信する前に、iocb->dataに関数ポインタを付けるio_set_callbackを使用してコールバックを設定しました。最後に、io_geteventsを使用して完了したイベントを取得し、各コールバックを実行します。libaioコールバックでのコンテキストデータの適切な処理?

私は、コールバック内でいくつかのコンテキスト情報(送信タイムスタンプなど)を使用できるようにしたいと考えています。私がこれを行うと考えることができる唯一の方法は、io_geteventsを使い続けることですが、iocb->dataはコンテキストとコールバックを持つ構造体を指しています。

io_geteventsを使用すると、このような処理を行う方法は他にありますか?iocb->dataはそのままですか? iocb->dataが関数を指していない場合、libaioが自動的にコールバックを実行する別の方法があります。

ここでの説明はうまくいくはずです。 libaioのドキュメントは本当に欠けているようです。

答えて

4

典型的な解決策は、iocbから「派生」して、io_getevents()から構造体に戻すポインタをキャストすることです。このような何か:

struct my_iocb { 
    iocb cb; 
    void* userdata; 
    // ... anything else 
}; 

あなたのジョブを発行すると、あなたはそれ時またはバッチ内のいずれかを実行するかどうか、あなたは彼らのようにmy_iocbを指すことを意味ポインタiocbに構造体の配列を、提供よく

あなたが戻ってio_getevents()からの通知を取得するとき、あなたは、単にあなた自身のタイプにio_event::objポインタをキャスト:

io_event events[512]; 
int num_events = io_getevents(ioctx, 1, 512, events, NULL); 
for (int i = 0; i < num_events; ++i) { 
    my_iocb* job = (my_iocb*)events[i].obj; 
    // .. do stuff with job 
} 

あなたはio_geteventsでブロックしたくないが、代わりにファイルディスクリプタを介して通知された場合(select()またはepoll()でブロックできるように、より便利かもしれません)、私は(文書化されていない)eventfdインテグレーションの使用をお勧めします。

aiocbを、io_set_eventfd(iocb* cb, int fd)のeventfdファイル記述子に結びつけることができます。ジョブが完了するたびに、eventfdが1だけインクリメントされます。

注意、あなたはこのメカニズムを使用している場合、のeventfdカウンタがそうでなければ、あなたがのeventfdを読んだときから、競合状態を導入し、そこにあったものよりも(io_getevents()付き)10文脈からより多くの仕事を読んだことがないことが非常に重要ですカウンターに入れ、仕事を刈り取る。

+0

この最後の夜のようなものを一緒に震わせた。あなたの答えは間違いなく、マニュアルページから欠けているいくつかのギャップを埋める! –