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\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).
Linux下使用inotify实现对文件的监控的更多相关文章
- linux设置rsync+inotify实时同步文件
linux设置rsync+inotify实时同步文件 应用场景: 同步接收方:test01 接收目录:/opt/software/test/a/ 同步发起方:test02 同步目录:/opt/so ...
- linux 下C语言编程库文件处理与Makefile编写
做开发快3年了,在linux下编译安装软件算是家常便饭了.就拿gcc来说,都有不下10次了,可基本每次都会碰到些奇奇怪怪的问题.看来还是像vs.codeblocks这样的ide把人弄蠢了.便下定决心一 ...
- Linux下用rm删除的文件的恢复方法
Linux下用rm删除的文件的恢复方法_Linux教程_Linux公社-Linux系统门户网站https://www.linuxidc.com/Linux/2008-08/14744.htm linu ...
- linux下查找指定后缀的文件
1.linux下查找指定后缀的文件 例如查找当前目录下的所有后缀名时.c或.h的文件 find . -type f -regex ".*\.\(c\|h\)"
- Linux下自动清除MySQL日志文件
MySQL运行过程中会生成大量的日志文件,占用不少空间,修改my.cnf文件配置bin-log过期时间,在Linux下自动清除MySQL日志文件 [mysqld] expire-logs-days= ...
- Linux下的文件结构,及对应文件夹的作用
Linux下的文件结构,及对应文件夹的作用 /bin 二进制可执行命令 /dev 设备特殊文件 /etc 系统管理和配置文件 /etc/rc.d 启动的配置文件和脚本 /home 用户主目录的基点,比 ...
- linux下添加用户并将文件夹授权给某一个用户
### linux下添加用户并将文件夹授权给某一个用户 背景:在做一个项目时,需要外包的前端人员调试测试环境的页面,但是又不能给他服务器的账号信息,就在服务器上新添加一个子账户,再给这个账户项目文件的 ...
- Linux下的命令,删除文件夹下的所有文件,而不删除文件夹本身
Linux下的命令,删除文件夹下的所有文件,而不删除文件夹本身 rm -rf *
- linux 下用find命令查找文件,rm命令删除文件
linux 下用find命令查找文件,rm命令删除文件. 删除指定目录下指定文件find 要查找的目录名 -name .svn |xargs rm -rf 删除指定名称的文件或文件夹: find -t ...
随机推荐
- redhat 7.x 、redhat 6.x查看硬盘UUID方法
1.查看磁盘分区UUID: [root@rac01 ~]# blkid /dev/sdb1: UUID="6bba92c4-0b25-4cc4-9442-ca87c563720a" ...
- scp免密码拷贝和ssh免密码登录
版权声明:本文为博主原创文章,未经允许不得转载. 在平常的工作中经常在两个服务器之间传输文件,而且经常从本地远程登录服务器,每次都要输入密码显然很没效率,这时候该怎么办呢? 首先假设服务器A和B,要想 ...
- CentOS 7 设置开机自启动
创建脚本: #!/bin/bash echo "hello!" # 启动虚拟环境 cd /data/env/crmenv/bin/ source activ ...
- SolrCloud 概念
原文链接 https://www.w3cschool.cn/solr_doc 当您的集合对于一个节点来说太大时,您可以通过创建多个分片将其分解并分段存储. 碎片是集合的逻辑分区,包含集合中的文档的子集 ...
- POJ 1611 The Suspects (并查集求数量)
Description Severe acute respiratory syndrome (SARS), an atypical pneumonia of unknown aetiology, wa ...
- Vijos 1308 埃及分数(迭代加深搜索)
题意: 输入a.b, 求a/b 可以由多少个埃及分数组成. 埃及分数是形如1/a , a是自然数的分数. 如2/3 = 1/2 + 1/6, 但埃及分数中不允许有相同的 ,如不可以2/3 = 1/3 ...
- js作用域的几个问题
按照<权威指南>的说法,全局的变量作用域是全局性的,在js代码中,他处处都有定义.而在函数之内声明的变量,就只有在函数体内有定义了.函数的参数也是局部变量,他们只在函数体内部有定义.在函数 ...
- [Go]结构体及其方法
结构体类型可以包含若干字段,每个字段通常都需要有确切的名字和类型.也可以不包含任何字段,这样并不是没有意义的,因为还可以为这些类型关联上一些方法,这里可以把方法看作事函数的特殊版本. 函数事独立的程序 ...
- 洛谷P1759 通天之潜水
题目背景 直达通天路·小A历险记第三篇 题目描述 在猴王的帮助下,小A终于走出了这篇荒山,却发现一条波涛汹涌的河拦在了自己的面前.河面上并没有船,但好在小A有n个潜水工具.由于他还要背重重的背包,所以 ...
- boost thread 在非正常退出时 内存泄露问题
在使用boost的thread库的时候,如果主程序退出,thread创建的线程不做任何处理,则会出现内存泄露. 解决方法: 在主线程退出时,对所有thread使用interrupt()命令,然后主程序 ...