linux检测目录下文件变化

Linux 检测目录下文件变化api

前排致谢:
http://blog.csdn.net/myiloveuuu/article/details/53296619

最近要实现一个需求:
当摄像头动态检测变化后会保存一段时间视频画面并写入到某个目录下,而我需要提供一个api去获取是否有新文件生成。经过查阅网友分享得知,在Linux 2.6.13内核中引入inotify接口用于检测文件及目录变化。

本文可能有所疏漏,可参阅:man inotify

1 代码

先上代码,再逐步分析。

#include <stdio.h>
#include <stdlib.h>
#include <sys/inotify.h>
#include <unistd.h>
static void *PIRThread(void *id)
{
int fd = 0;  
char data[255] = {0};  
char* eventptr;
int step = 0;
struct inotify_event event;

fd = inotify_init1(IN_NONBLOCK);
int step = 0;
inotify_add_watch(fd, "/home/xx.xx/work/v50/IISC/media",IN_CREATE|IN_MOVED_TO);//监听是否有新文件 
while(1)
{
    readLength = read(fd, data, 255);
    if(readLength > 0)
    {
//解析事件描述结构体
         cout <<  readLength << endl;
        eventptr = data;
        event.wd = *((int*)eventptr);
        step +=sizeof(int);
        //eventptr += sizeof(int);
        event.mask = *((uint32_t*)(eventptr+step));
        step  += sizeof(uint32_t);
        event.cookie  = *((uint32_t*)(eventptr+step));
        step += sizeof(uint32_t);
        event.len  = *((uint32_t*)(eventptr+step));
        step += sizeof(uint32_t);
        string filename(eventptr+step, event.len);
        step = 0;

        cout << "wd:"<<event.wd << endl;
        cout << "mask:"<<event.mask << endl;
        cout << "cookie:"<<event.cookie  << endl;
        cout << "len:" <<event.len<< endl;
        cout << "filename:" <<filename << endl;

        if(event.mask == IN_CREATE)
            cout <<"new file was created:"<< event.mask << endl;
        else if(event.mask == IN_MOVED_TO)
            cout <<"new file was move to mydir"<< event.mask << endl;
    } 
    sleep(1);
}
pthread_exit(0);
}

2 代码分析

代码单独开辟一个线程用于检测文件下文件变化,并每秒读取一次。

2.1 inotify_init1(int flags)

可传入参数:IN_NONBLOCK 不阻塞 ,IN_CLOEXEC 阻塞

初始化inotify实例并返回一个描述符。

fd = inotify_init1(IN_NONBLOCK);

即为不阻塞方式检测文件变化。
如果参数CLOEXEC 就会阻塞在 read函数,直到检测成功才接着往下执行。

2.2 int inotify_add_watch(int fd, const char *pathname, uint32_t mask); ###

参数:

  • fd是inotify文件描述符,inotify_init()的返回值
  • pathname是要监听的文件的路径
  • mask是指定要监视哪些事件(值在2.3中)
    返回:
    返回值是一个inotify标识(wd),即该监听事件标志与fd不是同一个东西。

    inotify_add_watch(fd, “/home/jw.li/work/v50/IISC/media”,IN_CREATE|IN_MOVED_TO);

2.3 相应事件

  • IN_ACCESS: 文件被访问
  • IN_ATTRIB:元数据被改变,例如权限、时间戳、扩展属性、链接数、UID、GID等
  • IN_CLOSE_WRITE:关闭打开写的文件
  • IN_CLOSE_NOWRITE: 和IN_CLOSE_WRITE刚好相反,关闭不是打开写的文件
  • IN_CREATE:这个是用于目录,在监控的目录中创建目录或文件时发生
  • IN_DELETE:这个也是用于目录,在监控的目录中删除目录或文件时发生
  • IN_DELETE_SELF:监控的目录或文件本身被删除
  • IN_MODIFY:文件被修改,这种事件会用到inotify_event中的cookie。
  • IN_MOVE_SELF:监控的文件或目录本身被移动
  • IN_MOVED_FROM: 从监控的目录中移出文件
  • IN_MOVED_TO:向监控的目录中移入文件
  • IN_OPEN: 文件被打开

2.4 read(fd, buf, count); 读取事件

参数:

  • fd是inotify文件描述符,inotify_init()的返回值
  • buf用于读取inotify事件结构的buf(自己开辟传入)
  • Count 读取buffer大小(s)

返回:

  • 监听时间均未发生时,返回值为-1
  • 监听事件发生时,返回值为inotify事件结构大小

    readLength = read(fd, data, 255);

即如果监听事件发生,data值为struct inotify_event event结构体数据,readLength为 结构体数据大小,返回,truct inotify_event event内容在2.5中介绍。

2.5 inotify_event

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是inotify标识符,inotify_add_watch()的返回值;

  • mask就是发生的事件掩码;
  • cookie这个好像只在rename中使用,
  • len 原本以为是文件名长度但测试发现并不是。
  • name就是检测改变的文件的名字

解析:
我们可以通过指针按照结构体中各元素大小解析出数据

        char* eventptr;
        int step = 0;
        struct inotify_event event;

        eventptr = data;
        event.wd = *((int*)eventptr);
        step +=sizeof(int);
        //eventptr += sizeof(int);
        event.mask = *((uint32_t*)(eventptr+step));
        step  += sizeof(uint32_t);
        event.cookie  = *((uint32_t*)(eventptr+step));
        step += sizeof(uint32_t);
        event.len  = *((uint32_t*)(eventptr+step));
        step += sizeof(uint32_t);
        string filename(eventptr+step, event.len);
        step = 0;

2.6 通过解析出的 event.mask与事件做对比对各事件进行处理。

if(event.mask == IN_CREATE)
cout <<”new file was created:”<< event.mask << endl;
else if(event.mask == IN_MOVED_TO)
cout <<”new file was move to mydir”<< event.mask << endl;

sample:
linux 环境
https://github.com/CollapsarLi/li_checkfilechange_sample.git

git clone https://github.com/CollapsarLi/li_checkfilechange_sample.git;
cd cd li_checkfilechange_sample/
阅读 readme

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值