今天要完成类似配置文件动态刷新的功能,就查了下linux中类似的文件变化通知机制,遂发现inotify。学习了数小时,略有收获,就总结下。
inotify是linux中用来监控文件系统的一种策略。(The inotify API provides a mechanism for monitoring file system events)它可以监控一个目录或指定的文件。
libevent是一个高性能的事件通知库。当它监控的fd变化时,会调用指定的回调函数。
我,apicaller,编程。
直接上代码:
#include <sys/inotify.h>
#include <event.h>
#include <event2/event.h>
#include <stdio.h>
#include <stdlib.h>
void watch_notify_events(int fd, short events, void *arg)
{
char buf[512];
int rc;
struct inotify_event *inotify_ev = NULL;
rc = read(fd, buf, sizeof(buf));
inotify_ev = (struct inotify_event *)buf;
if (inotify_ev == NULL)
return;
if(inotify_ev->mask & IN_CLOSE_WRITE)
printf("file modifiy\n");
}
int main(int argc, char **argv)
{
int inotify_fd;
int wd;
int rc;
struct event_base *ev_base;
struct event *event;
inotify_fd = inotify_init();
if (inotify_fd < 0) {
printf("init inotify error\n");
return 0;
}
wd = inotify_add_watch(inotify_fd, argv[1], IN_CLOSE_WRITE);
ev_base = event_base_new();
event = event_new(ev_base,
inotify_fd,
EV_READ | EV_PERSIST,
watch_notify_events,
NULL);
event_add(event, NULL);
event_base_dispatch(ev_base);
rc = inotify_rm_watch(inotify_fd, wd);
if (rc < 0) {
printf("remove file error\n");
return 0;
}
close(inotify_fd);
}
代码仅是个DEMO,还有许多不足,别太在意。
代码中,关于inotify我有两点想说明:
1.inotify_add_watch(...., IN_CLOSE_WRITE)。这里模式我并没有指定IN_MODIFY,这是因为如果用vim作修改的话,IN_MODIFY将无效(不会通知)。其实是因为在用vim修改文件时,从打开文件到修改完成退出,要经历很多步骤,包括创建临时文件.swp和.swx来完成复制,再销毁。具体细节,可以查看vim相关机制。
2.inotify_event->name和inotify_event->len。我在学习inotify时,可被这两个东西搞懵逼了很久。明明文件作了修改,相应的printf语句也有,可是这两个值都为空。翻阅linux man page中才发现,name和len只在监控目录时才会有值。name为作出修改的文件;len为name的长度。