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シャツ欲しい!おっお!