Linux下使用inotify实现对文件的监控
2015-08-19 13:21
721 查看
项目中,要实现用户通过网页设置参数,后台接收数据然后写串口。
网页写数据到本地文件,使用inotify监控文件的IN_MODIFY事件,当文件被修改,然后触发写串口事件。
第一个程序仅仅把要监控的文件加入watch_list中,执行程序,发现select返回,只能检测到文件被修改,
但是如果同时监控多个文件,却不能区分是哪个文件被改动了。
struct inotify_event {
int wd; /* Watch descriptor */
uint32_t mask; /* Mask of events */
uint32_t cookie; /* Unique cookie associating related
events (for rename(2)) */
uint32_t len; /* Size of name field */
char name[]; /* Optional null-terminated name */
};
wd identifies the watch for which this event occurs. It is one of the watch descriptors returned by a previous call to inotify_add_watch(2).
mask contains bits that describe the event that occurred (see below).
cookie is a unique integer that connects related events. Currently this is only used for rename events, and allows the resulting pair of IN_MOVE_FROM
and IN_MOVE_TO events to be connected by the application.
The name field is only present when an event is returned for a file inside a watched directory; it identifies the file pathname relative to the watched
directory. This pathname is null-terminated, and may include further null bytes to align subsequent reads to a suitable address boundary.
The len field counts all of the bytes in name, including the null bytes; the length of each inotify_event structure is thus sizeof(inotify_event)+len.
The behavior when the buffer given to read(2) is too small to return information about the next event depends on the kernel version: in kernels before
2.6.21, read(2) returns 0; since kernel 2.6.21, read(2) fails with the error EINVAL.
又仔细阅读了man inotify,发现只有把目录添加到watch_list,才能获得是目录中的哪一个文件被修改了。
caution:当检测文件的IN_MODIFY事件的时候,会发现IN_MODIFY会触发多次
下面是原因
Q: What is the difference between IN_MODIFY and IN_CLOSE_WRITE?
The IN_MODIFY event is emitted on a file content change (e.g. via the write() syscall) while IN_CLOSE_WRITEoccurs on closing the changed file. It means each change operation causes one IN_MODIFY event (it may occurmany times during manipulations with an open
file) whereas IN_CLOSE_WRITE is emitted only once (on closingthe file).
引用地址:http://inotify.aiken.cz/?section=inotify&page=faq
网页写数据到本地文件,使用inotify监控文件的IN_MODIFY事件,当文件被修改,然后触发写串口事件。
第一个程序仅仅把要监控的文件加入watch_list中,执行程序,发现select返回,只能检测到文件被修改,
但是如果同时监控多个文件,却不能区分是哪个文件被改动了。
/*This is the sample program to notify us for the file creation and file deletion takes place in “/tmp” directory*/ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <errno.h> #include <sys/types.h> #include <linux/inotify.h> #define FILE1 "request" #define FILE2 "time" #define EVENT_SIZE ( sizeof (struct inotify_event) ) #define EVENT_BUF_LEN ( 1024 * ( EVENT_SIZE + 16 ) ) int main( ) { int length,i=0; int fd,maxfd; int wd1; int wd2; int ret; fd_set rfds; fd_set wfds; struct timeval tv; char buffer[EVENT_BUF_LEN]; /*creating the INOTIFY instance*/ fd = inotify_init(); /*checking for error*/ if ( fd < 0 ) { perror( "inotify_init" ); exit(-1); } /*adding the “/tmp” directory into watch list. Here, the suggestion is to validate the existence of the directory before adding into monitoring list.*/ wd1 = inotify_add_watch( fd,FILE1, IN_MODIFY); if(wd1 < 0) { perror("inotify_add_watch"); exit(-1); } wd2 = inotify_add_watch( fd,FILE2, IN_MODIFY); if(wd2 < 0) { perror("inotify_add_watch"); exit(-1); } /*read to determine the event change happens on “/tmp” directory. Actually this read blocks until the change event occurs*/ while(1) { printf("begining while\n"); FD_ZERO(&rfds); FD_SET(fd,&rfds); maxfd = fd + 1; tv.tv_sec = 10; tv.tv_usec = 0; printf("waiting select ...\n"); ret = select(maxfd,&rfds,NULL,NULL,&tv); switch(ret) { case -1: fprintf(stderr,"select failed\n"); break; case 0: fprintf(stderr,"select timeout...\n"); continue; default: fprintf(stderr,"fd is readable.\n"); length = read(fd,buffer,EVENT_BUF_LEN); printf("length=%d\n",length); if(length < 0) { perror("read"); exit(-1); } while(i < length) { fprintf(stderr,"inside while ...\n"); struct inotify_event *event = (struct inotify_event*)&buffer[i]; printf("event->len = %d\n",event->len); if(event->len) { if(event->mask & IN_MODIFY) { printf("detected file %s modified.\n",event->name); } } i += EVENT_SIZE + event->len; } i = 0; inotify_rm_watch(fd,wd1); inotify_rm_watch(fd,wd2); close(fd); fd = inotify_init(); wd1 = inotify_add_watch( fd,FILE1, IN_MODIFY); wd2 = inotify_add_watch( fd,FILE2, IN_MODIFY); break; /* printf("detected file modified\n"); sleep(1); inotify_rm_watch(fd,wd); close(fd); fd = inotify_init(); wd = inotify_add_watch( fd,TEST_FILE, IN_MODIFY); break; */ } printf("break switch\n"); } inotify_rm_watch(fd,wd1); inotify_rm_watch(fd,wd2); close(fd); return 0; }
struct inotify_event {
int wd; /* Watch descriptor */
uint32_t mask; /* Mask of events */
uint32_t cookie; /* Unique cookie associating related
events (for rename(2)) */
uint32_t len; /* Size of name field */
char name[]; /* Optional null-terminated name */
};
wd identifies the watch for which this event occurs. It is one of the watch descriptors returned by a previous call to inotify_add_watch(2).
mask contains bits that describe the event that occurred (see below).
cookie is a unique integer that connects related events. Currently this is only used for rename events, and allows the resulting pair of IN_MOVE_FROM
and IN_MOVE_TO events to be connected by the application.
The name field is only present when an event is returned for a file inside a watched directory; it identifies the file pathname relative to the watched
directory. This pathname is null-terminated, and may include further null bytes to align subsequent reads to a suitable address boundary.
The len field counts all of the bytes in name, including the null bytes; the length of each inotify_event structure is thus sizeof(inotify_event)+len.
The behavior when the buffer given to read(2) is too small to return information about the next event depends on the kernel version: in kernels before
2.6.21, read(2) returns 0; since kernel 2.6.21, read(2) fails with the error EINVAL.
又仔细阅读了man inotify,发现只有把目录添加到watch_list,才能获得是目录中的哪一个文件被修改了。
/*This is the sample program to notify us for the file creation and file deletion takes place in “/tmp” directory*/ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <errno.h> #include <sys/types.h> #include <linux/inotify.h> #define MONITOR_PATH "/home/lucifer/working/2015_08_19" #define EVENT_SIZE ( sizeof (struct inotify_event) ) #define EVENT_BUF_LEN ( 1024 * ( EVENT_SIZE + 16 ) ) int main( ) { int length,i=0; int fd,maxfd; int wd1; int ret; fd_set rfds; fd_set wfds; struct timeval tv; char buffer[EVENT_BUF_LEN]; /*creating the INOTIFY instance*/ fd = inotify_init(); /*checking for error*/ if ( fd < 0 ) { perror( "inotify_init" ); exit(-1); } /*adding the “/tmp” directory into watch list. Here, the suggestion is to validate the existence of the directory before adding into monitoring list.*/ wd1 = inotify_add_watch( fd,MONITOR_PATH, IN_MODIFY); if(wd1 < 0) { perror("inotify_add_watch"); exit(-1); } /*read to determine the event change happens on “/tmp” directory. Actually this read blocks until the change event occurs*/ while(1) { printf("begining while\n"); FD_ZERO(&rfds); FD_SET(fd,&rfds); maxfd = fd + 1; tv.tv_sec = 10; tv.tv_usec = 0; printf("waiting select ...\n"); ret = select(maxfd,&rfds,NULL,NULL,&tv); switch(ret) { case -1: fprintf(stderr,"select failed\n"); break; case 0: fprintf(stderr,"select timeout...\n"); continue; default: fprintf(stderr,"fd is readable.\n"); length = read(fd,buffer,EVENT_BUF_LEN); printf("length=%d\n",length); if(length < 0) { perror("read"); exit(-1); } while(i < length) { fprintf(stderr,"inside while ...\n"); struct inotify_event *event = (struct inotify_event*)&buffer[i]; printf("event->len = %d\n",event->len); if(event->len) { if(event->mask & IN_MODIFY) { printf("detected file %s modified.\n",event->name); } } i += EVENT_SIZE + event->len; } i = 0; inotify_rm_watch(fd,wd1); close(fd); fd = inotify_init(); wd1 = inotify_add_watch( fd,MONITOR_PATH, IN_MODIFY); break; /* printf("detected file modified\n"); sleep(1); inotify_rm_watch(fd,wd); close(fd); fd = inotify_init(); wd = inotify_add_watch( fd,TEST_FILE, IN_MODIFY); break; */ } printf("break switch\n"); } inotify_rm_watch(fd,wd1); close(fd); return 0; }
caution:当检测文件的IN_MODIFY事件的时候,会发现IN_MODIFY会触发多次
下面是原因
Q: What is the difference between IN_MODIFY and IN_CLOSE_WRITE?
The IN_MODIFY event is emitted on a file content change (e.g. via the write() syscall) while IN_CLOSE_WRITEoccurs on closing the changed file. It means each change operation causes one IN_MODIFY event (it may occurmany times during manipulations with an open
file) whereas IN_CLOSE_WRITE is emitted only once (on closingthe file).
引用地址:http://inotify.aiken.cz/?section=inotify&page=faq
相关文章推荐
- linux 命令 - 切换目录cd
- WIN版的Jenkins Master加入LINUX的SLAVE节点,并作C++程序的集成交付
- linux 使用 lockf命令防止脚本重复运行
- linux命令 - 建立目录mkdir
- Linux下禁用Firefox浏览器的静默请求教程
- Linux命令(二)
- 注意php建立文件(夹)与linux umask的问题
- centos下 安装 rvm
- Linux命令(一)
- 在嵌入式Linux和PC机Linux下使用popen函数时,程序运行结果有差异。
- Linux 限制进程占用CPU
- Redhat配置使用centos的yum源
- centos安装pip和mitmproxy
- Linux常用命令
- linux下的定时任务
- linux笔记之1--文件系统+创建、删除文件和文件夹命令
- Linux LVS-NAT实例演示
- centos下把python版本升级成2.7
- Linux内核的进程切换(上)
- Linux 环境进程间通信(六) 套接口