libevent+inotify实现配置文件实时读取
Posted 尚书左仆射
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了libevent+inotify实现配置文件实时读取相关的知识,希望对你有一定的参考价值。
有些配置文件需要被频繁使用,但是又需要支持根据“场景”进行模式切换。如果每次都重新读取势必影响服务响应效率,折衷的方式是定时重新读取,比如5分钟。但最好的方式是在真正需要的时候在重新读取,即,文件修改之后。
那么如何得知所关注的文件已经被修改?
Inotify 是一个 Linux特性,它监控文件系统操作,比如读取、写入和创建。Inotify 反应灵敏,用法非常简单,并且比 cron 任务的繁忙轮询高效得多。可以监控一个目录或指定的文件。
Inotify 可监视的文件系统事件:
IN_ACCESS : 即文件被访问
IN_MODIFY : 文件被 write
IN_ATTRIB : 文件属性被修改,如 chmod、chown、touch 等
IN_CLOSE_WRITE : 可写文件被 close
IN_CLOSE_NOWRITE : 不可写文件被 close
IN_OPEN : 文件被open
IN_MOVED_FROM : 文件被移走,如 mv
IN_MOVED_TO : 文件被移来,如 mv、cp
IN_CREATE : 创建新文件
IN_DELETE : 文件被删除,如 rm
IN_DELETE_SELF : 自删除,即一个可执行文件在执行时删除自己
IN_MOVE_SELF : 自移动,即一个可执行文件在执行时移动自己
IN_UNMOUNT : 宿主文件系统被 umount
IN_CLOSE : 文件被关闭,等同于(IN_CLOSE_WRITE | IN_CLOSE_NOWRITE)
IN_MOVE : 文件被移动,等同于(IN_MOVED_FROM | IN_MOVED_TO)
注:上述事件,目录和文件同样适用。
下面使用libevent+inotify来实现文件修改通知。为了定时输出监控文件的内容,我增加了一个定时事件,在定时回调中输出目标文件的内容。
主要测试代码:
static void show_file()
//*
// 受监控的文件
const char* file_path = "./settings/other/checkModify.txt";
ifstream ifs;
ifs.open(file_path, ios::binary);
if (!ifs.is_open())
cout<<"file open failed!!!"<<endl;
return;
// 定位到流末尾以获得长度;
ifs.seekg(0, ifs.end);
int length = ifs.tellg();
// 再定位到开始处进行读取;
ifs.seekg(0, ifs.beg);
// 定义一个buffer;
char *buffer = new char[length];
// 将数据读入buffer;
ifs.read(buffer, length);
cout<<buffer<<endl;
delete[] buffer;
ifs.close();
//*/
// timer callback 定时展示文件内容
void on_timer(int sock, short event, void *arg)
cout << "---In timer callback---" << endl;
show_file();
struct timeval tv;
tv.tv_sec = 5;
tv.tv_usec = 0;
// 重新添加定时事件(定时事件触发后默认自动删除)
event_add((struct event*)arg, &tv);
cout << "---Timer callback end---" << endl;
// 捕获到文件状态改变时的回调
void watch_notify_events(int fd, short events, void *arg)
cout<<"---In watch_notify_events---"<<endl;
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_MODIFY)
cout<<"file modifiy"<<endl;
show_file();
// 主函数
int main()
/// inotify
int inotify_fd;
inotify_fd = inotify_init();
if (inotify_fd < 0)
cout<<"init inotify error"<<endl;
return -1;
int wd;
const char* notify_path = "./settings/other";
wd = inotify_add_watch(inotify_fd, notify_path, IN_MODIFY);
// 初始化
event_init();
struct event evTimer;
// 设置定时事件
evtimer_set(&evTimer, on_timer, &evTimer);
struct timeval tv;
tv.tv_sec = 5;
tv.tv_usec = 0;
// 添加定时事件
event_add(&evTimer, &tv);
// add inotify event
struct event evNotify;
event_set(&evNotify, inotify_fd, EV_READ | EV_PERSIST, watch_notify_events, NULL);
event_add(&evNotify, NULL);
// 事件循环
event_dispatch();
int rc;
rc = inotify_rm_watch(inotify_fd, wd);
if (rc < 0)
cout<<"remove file error"<<endl;
return -2;
close(inotify_fd);
return 0;
执行情况如下:
代码正常运行需要libevent库的支持,需先完成安装,编译时增加 -levent参数。目标文件初始化内容为“Not Modifyed!!!”,修改后内容为“Now it’s Modifyed!!!”,修改过程中IN_MODIFY文件状态所产生的信号事件通过Inotify机制捕捉到后,经过libevent事件分发到对应的回调函数进行处理。
以上是关于libevent+inotify实现配置文件实时读取的主要内容,如果未能解决你的问题,请参考以下文章