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シャツ欲しい!おっお!
Linuxでaio
実装が2つある。以下、あくまで今の時点でのLinuxの場合の状況/実装のおはなし。
POSIX aio
- aio_read(3) とか aio_write(3), aio_error(3), aio_return(3) とか。
libaio
- http://lse.sourceforge.net/io/aio.html
- http://ftp.jaist.ac.jp/pub/Linux/Fedora/development/source/SRPMS/libaio-0.3.106-3.2.src.rpm とか
- io_prep_pread(2), io_prep_pwrite(2), io_submit(2), io_queue_init(2), io_queue_run(2) とか
- Linux独自
- ライブラリ関数じゃなくてシステムコール
- 裏でスレッド作ってごにょごにょとかはしない
- libaioのアーカイブのman/io.3に書いてあるサンプルコードがおもろい。
Copy file by using a async I/O state machine.
1. Start read request
2. When read completes turn it into a write request
3. When write completes decrement counter and free resourcesUsage: aiocp file(s) desination
-
- がーっと読んでがーっと書くんじゃなくて、チャンクにブツ切りにして、読んだら新しいファイルの同じオフセットのところへ書く、というのをチャンクごとにやる。ほんで、このreadとwriteは全部非同期。仮に、おっそいチャンクがあってもほかのチャンクたちは影響ない、おっそいread(やwrite)がいてもほかのチャンクのreadやwriteには影響ない。あ、影響ないってのはいいすぎか。I/Oブロックされてほかの処理に移れないってことがなくなる。
- イメージ的には、チーズをよってたかってみんなで一斉にちびっとずつ食べる感じ。