3

私はカーネルレベルの非同期I/O(つまりlibaio.h)を使用しています。struct iocbusingを送信する前に、関数ポインタをに固定するio_submitを使用してコールバックを設定しました。最後に、を使用して完了したイベントを取得し、各コールバックを実行します。io_set_callbackiocb->dataio_getevents

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

このようなことをするための他の方法はありますか、そしてiocb->data使用するときに手つかずであることが保証されていio_geteventsますか?私の理解では、関数を指していないlibaio場合に問題となるコールバックを自動的に実行する別の方法があります。iocb->data

ここでの説明があればいいのですが。のドキュメントはlibaio本当に不足しているようです。

4

1 に答える 1

4

私が想像する典型的な解決策の1つは、iocbから「派生」してから、取得したポインターをio_getevents()構造体にキャストすることです。このようなもの:

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

一度に1つずつ実行する場合でも、バッチで実行する場合でも、ジョブを発行するときは、構造体へのポインターiocbの配列を提供します。これは、構造体も指す可能性があることを意味しmy_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を使用して、eventfdファイル記述子に関連付けることができますio_set_eventfd(iocb* cb, int fd)。ジョブが完了するたびに、eventfdが1つインクリメントされます。

このメカニズムを使用する場合は、ioコンテキストから(を使用してio_getevents())eventfdカウンターが言ったよりも多くのジョブを読み取らないことが非常に重要です。そうしないと、eventfdカウンターを読み取ってジョブを取得したときに競合状態が発生します。 。

于 2012-03-23T07:50:46.067 に答える