kqueueを試す
ファイルの書き込み監視をする要件がでてきたので以前から気になっていたkqueueを試してみました。このあたりはBSD*なOSXの強みですね。
manしてみればわかるのですがインタフェースは
- int kqueue()
- int kevent()
- EV_SET()
の三つ。うち、EV_SETは単なるマクロですから実質2つのインタフェースしかありません。使い方は単純で、イベントキューの取得(kqueue)、と監視イベントの登録(EV_SET+kevent)そしてイベント監視(kevent)という至極単純な流れ。ADCにも FileNotificationという立派なサンプルがあるのですがこれ、ちょっと複雑なのでファイルの書き込み監視に特化してサンプルを作ってみました。
kque = kqueue();
struct kevent ke;
memset(&ke,0x00,sizeof(kevent));
int watch_description = open([@"/Path/To/Watch" fileSystemRepresentation],O_RDONLY,0);
EV_SET(
&ke,watch_description,EVFILT_VNODE,EV_ADD|EV_ENABLE|EV_CLEAR,NOTE_WRITE,0,NULL);
kevent(kque,&ke,1,NULL,0,NULL);
bRun = YES;
[NSThread
detachNewThreadSelector:@selector(watch:) toTarget:self withObject:nil];まず、キューの取得と監視の登録。キューの取得はそのまんま。監視の登録は対象のファイルデスクリプションを指定します。ここでは、監視したいパスのデスクリプションを指定しています。監視依頼と実際の監視はkevent()で行います。引数としてkeventを渡しますがこの中で監視の登録・削除・有効・無効などを指定するわけです。ここでは、ファイルシステムの監視をするので第三パラメタにEVFILT_VNODEを指定します。具体的な監視結果はkeventのfflagsで受け取ります。第四パラメタに新規監視の登録を指定しています。第五パラメタには第三パラメタで指定した監視結果のうち受け取りたいfflagsのフィルタを指定します。とりあえず書き込みだけを監視できればよいのでNOTE_WRITEを指定しています。
-(void)watch:(id)sender
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
struct kevent ke;
memset(&ke,0x00,sizeof(ke));
while(bRun)
{
if (kevent(kque,NULL,0,&ke,1,NULL) > 0)
{
if ((ke.fflags & NOTE_WRITE) == NOTE_WRITE)
{
[[myOutlet cell] setStringValue:@"write now!"];
}
}
}
close(kque);
[pool release];
return ;
}で、肝心の監視なんですがこれもkevent()を使います。引数はキューと結果を受け取りたいkeventへのポインタ。ここでは指定していませんが最終パラメタでタイムアウト値も指定できるようです。あとは結果のチェックをするだけ。監視登録時のfflagsフィルタでNOTE_WRITEしか指定していないのでチェックは必要ではないのですが、複数のフィルタを指定した場合はこんな感じでチェックします。
監視フォルダ中の任意のファイルを書き込みモードでopenしただけでイベント通知があるので注意がいるかもしれません。例えば、vi /path/to/watch/a.txtととしただけでイベントが発生します。(実際に:q!で抜けたとしてもです。)ログを取ってみたらopen時に二回、書き込み時に四回、quit時にも一回のイベントが発生しています。テストはviでやったのでエディタの動作として複数回の書き込みがなされている可能性もあるのですが(*swpファイルの扱いとかね)いづれにせよ実際には監視前の状態を把握しておいて、イベント発生時に監視前の状態と比較するというような処理が必要になるような気がします。
| 添付 | サイズ |
|---|---|
| kq.zip | 41.41 KB |










最近のコメント
2 weeks 2 days ago
3 weeks 4 hours ago
3 weeks 6 days ago
3 weeks 6 days ago
6 weeks 6 days ago
6 weeks 6 days ago
13 weeks 21 hours ago
22 weeks 6 days ago
22 weeks 6 days ago
25 weeks 4 days ago