FreeBSDでaio - その2

id:hirose31:20070719:1184773995 の続き)

できた。

  • my_aiocb.aio_sigevent.sigev_notify = SIGEV_KEVENT を使えばおk

その名の通り、kqueue + kevent を組み合わせて非同期I/Oできたす。

  • 必要な大きさのstruct kevent *をまろっくして
  • kqueue()をこさえて
  • aiocbの通知設定をして
my_aiocb.aio_sigevent.sigev_notify          = SIGEV_KEVENT;
my_aiocb.aio_sigevent.sigev_notify_kqueue   = my_kqueue;
my_aiocb.aio_sigevent.sigev_value.sival_ptr = iocb;
  • aio_read or aio_write して非同期I/Oリクエストをして
  • keventでI/O完了したのを取り出して
  • あとは煮るなり焼くなり


若干はまったのは、struct sigeventのメンバがsival_ptrじゃなくてsigval_ptrな点。(Linuxだとgなしのsival_ptrなの)
めんどいんで↓な感じに。(lighttpdからのパクり)

#if (defined(__FreeBSD__) || defined(__DragonFly__))
#  define sival_ptr   sigval_ptr
#endif


あと、1このkeventの配列に、aio_readとaio_writeを混在させたときに、kevent()後にreadとwriteを判別する方法がいまいちわからんかったす。

とりあえず、

    :    :
iocb->aio_lio_opcode = LIO_READ;
rc = aio_read(iocb);
    or
    :    :
iocb->aio_lio_opcode = LIO_WRITE;
rc = aio_write(iocb);

して、kevent()後に

    switch (cb->aio_lio_opcode) {
    case LIO_READ:
      rd_done(cb);
      break;
    case LIO_WRITE:
      wr_done(cb);
      break;
    default:
      TRACE("%s","aio_lio_opcode: unknown case. hmmmmmm.....");
      break;
    }

な感じで判別はできたんだけど、これがいけてる方法なのかよくわからず。


はてなスターTシャツ欲しい!おっお!