• Linux下使用inotify实现对文件的监控


    项目中,要实现用户通过网页设置參数,后台接收数据然后写串口。

    网页写数据到本地文件,使用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



  • 相关阅读:
    Android安全机制
    service不死之身
    图片加载机制比较
    handler机制面试
    SharedPreferences封装类
    文字太长自动缩小
    ANR
    onCreate源码分析
    线程池的启动策略
    Oauth认证协议
  • 原文地址:https://www.cnblogs.com/wzzkaifa/p/6903473.html
Copyright © 2020-2023  润新知