项目中,要实现用户通过网页设置參数,后台接收数据然后写串口。
网页写数据到本地文件,使用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 "); FD_ZERO(&rfds); FD_SET(fd,&rfds); maxfd = fd + 1; tv.tv_sec = 10; tv.tv_usec = 0; printf("waiting select ... "); ret = select(maxfd,&rfds,NULL,NULL,&tv); switch(ret) { case -1: fprintf(stderr,"select failed "); break; case 0: fprintf(stderr,"select timeout... "); continue; default: fprintf(stderr,"fd is readable. "); length = read(fd,buffer,EVENT_BUF_LEN); printf("length=%d ",length); if(length < 0) { perror("read"); exit(-1); } while(i < length) { fprintf(stderr,"inside while ... "); struct inotify_event *event = (struct inotify_event*)&buffer[i]; printf("event->len = %d ",event->len); if(event->len) { if(event->mask & IN_MODIFY) { printf("detected file %s modified. ",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 "); 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 "); } 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 "); FD_ZERO(&rfds); FD_SET(fd,&rfds); maxfd = fd + 1; tv.tv_sec = 10; tv.tv_usec = 0; printf("waiting select ... "); ret = select(maxfd,&rfds,NULL,NULL,&tv); switch(ret) { case -1: fprintf(stderr,"select failed "); break; case 0: fprintf(stderr,"select timeout... "); continue; default: fprintf(stderr,"fd is readable. "); length = read(fd,buffer,EVENT_BUF_LEN); printf("length=%d ",length); if(length < 0) { perror("read"); exit(-1); } while(i < length) { fprintf(stderr,"inside while ... "); struct inotify_event *event = (struct inotify_event*)&buffer[i]; printf("event->len = %d ",event->len); if(event->len) { if(event->mask & IN_MODIFY) { printf("detected file %s modified. ",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 "); 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 "); } 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