Linux系统开发程序,有时候需要监控配置文件的变化,做出相应操作,下面将介绍常用的文件、目录监控方法:
函数介绍:
1.Inotify系列函数:
Inotify_init(void)
系统返回一个文件描述符,使用完毕需要释放(close)
2.Inotify_add_watch(int fd, const char *pathname, unsigned int mask)
添加对指定文件的监控,可以选择需要监控的事件(设置mask);
3.Inotify_rm_watch(int fd, unsigned int wd)
从fd指定的inotify实例中,删除wd指定的监控项
那么inotify事件有哪些?
1.常见的事件如下:
IN_ACCESS:文件被访问(read)
IN_ATTRIB:文件元数据改变
IN_CLOSE_WRITE:关闭为了写入而打开的文件
一般我们可以使用read从fd中读取事件,当无事件发生,则read会阻塞等待,当有事件发生,则返回inotify_event结构:
Struct inotify_event{
Int wd;
Unsigned int mask
Unsigned int cookie;
Unsigned int len;
Char name[];
};
下面用一个简单的示例演示循环监控文件变化:
int ret = 0;
char buffer[MAX_BUFF] = {0};
int fd = inotify_init();
if(fd < 0){
perror("init inotify failed.");
return;
}
int wd = inotify_add_watch(fd, "/home/test.txt", IN_MODIFY | IN_CLOSE_WRITE | IN_IGNORED | IN_ATTRIB);//这里加了两个事件,稍后介绍
if(wd < 0){
printf("cannot add watch for test.txt.\n");
close(fd);//释放
return;
}
fd_set rfds;
while(1){
FD_ZERO(&rfds);
FD_SET(fd, &rfds);
ret = select(fd+1, &rfds, NULL, NULL, NULL);//监控read
if(ret <= 0){//如果设置超时,可以做一些其他事情
continue;
}
//event happened, so something
bzero(buffer, sizeof(buffer));
bet = (0 | read(fd, buffer, MAX_BUFF));
if(ret < 0){
printf("read inotify failed.");
break;
}
int index = 0;
while(index < ret){
struct inotify_event *pevent = (struct inotify_event*)&buffer[index];
unsigned int event_size = offsetof(struct inotify_event, name) + pevent->len;
index += (0 | event_size);
printf("event[wd:%d,mask:%u,cookie:%u,len:%u].", pevent->wd, pevent->mask, pevent->cookie, pevent->len);
if(pevent->mask & IN_MODIFY){
//do something
}
if(pevent->mask & IN_CLOSE_WRITE){
//do something
}
if((pevent->mask & IN_IGNORED) || (pevent->mask & IN_ATTRIB)){
//当触发IN_IGNORED或IN_ATTRIB事件时,需要重新调用inotify_add_watch,否则就只能检测一次,比如我们vi或mv文件时就会出现此种情况
wd = inotify_add_watch(fd, "/home/test.txt", IN_MODIFY | IN_CLOSE_WRITE | IN_IGNORED | IN_ATTRIB );
}
}//end while index
}//end while 1
inotify_rm_watch(fd,wd);
close(fd);
参考文档:https://blog.flowlore.com/passages/inotify-shi-yong-jiao-cheng/