Linux目录、文件事件监控

    之前开发一些Linux程序的时候,想要监控文件或者文件夹被改动的事件,但是没有找到方法。今天在看Linux/UNIX系统编程手册这本书的时候,看到有一章专门讲监控文件事件,才顿悟自己还是看书看的太少了。因此写这部博客记录一下,后续若用到,也好马上用到。

    从内核2.6.13起,Linux就提供了inotify机制,以允许应用程序监控文件事件。inotify主要有以下API:

    int inotify_init(void):创建一个新的inotify实体,该调用返回一个fd文件句柄

    int inotify_add_watch(int fd, const char *pathname, uint32_t mask):将pathname路径添加到监控列表,其中fd是inotify_init时返回的值,mask是要监控的事件掩码。该调用返回一个wd句柄。mask包含的事件见下面的表

    int inotify_rm_watch(int fd, uint32_t wd):将inotify_add_watch返回生成的wd,从inotify实例中移除监控。删除监控会生成一个IN_IGNORED事件。

    还有一个结构体

    struct inotify_event{

        int wd; /*Watch descriptor on which event occurred*/

        uint32_t mask;  /*Bts desccribing event that occurred */

        uint32_t cookie;  /* cookieforrelatedevents(forrename()) */

        uint32_t len; /* Size of 'name' field*/

        char name[];   /* Optional null-terminated filename */

    }

示例代码如下:

#include <sys/inotify.h>   /*这个是inotify API的头文件,必须引用*/
#include <limits.h>
#include <stdlib.h>
#include <stdio.h>

#define BUF_LEN (10 * (sizeof(struct inotify_event)) + NAME_MAX + 1)

static void displayInotifyEvent(struct inotify_event *event)
{
        if(event->cookie > 0)
                printf("   cookie = %4d", event->cookie);

        printf("mask or event:");
        if(event->mask & IN_ACCESS) printf("IN_ACCESS ");
        if(event->mask & IN_ATTRIB) printf("IN_ATTRIB ");
        if(event->mask & IN_CLOSE_NOWRITE) printf("IN_CLOSE_NOWRITE");
        if(event->mask & IN_CLOSE_WRITE) printf("IN_CLOSE_WRITE");
        if(event->mask & IN_CREATE) printf("IN_CREATE");
        if(event->mask & IN_DELETE) printf("IN_DELETE");
        if(event->mask & IN_MODIFY) printf("IN_MODIFY");
        if(event->mask & IN_OPEN) printf("IN_OPEN");
        printf("\n");

        if(event->len > 0)
                printf("  name=%s\n", event->name);
}

int main(){
        int ret = -1;
        int notify_handle = -1;
        int notify_add_handle = -1;
        struct inotify_event *event;
        char *p;
        char buf[BUF_LEN];

        notify_handle = inotify_init1(IN_NONBLOCK);
        printf("inotify_init ret:%d!\n", notify_handle);
        notify_add_handle = inotify_add_watch(notify_handle, "testdir", IN_ALL_EVENTS/*IN_ATTRIB | IN_ACCESS | IN_MODIFY | IN_OPEN*/);
       while(1){
                int num = read(notify_handle, buf, BUF_LEN);
                for(p=buf; p<buf+num;)
                {
                        event = (struct inotify_event *)buf;
                        displayInotifyEvent(event);
                        p+=sizeof(struct inotify_event) + event->len;
                        usleep(500*1000);
                }
        }
        return 0;
}

编译运行后,就可以监控同级目录下的testdir目录了。当testdir目录有文件生成、修改、删除时。read就可以读到该事件的缓冲数据,对缓冲数据进行解析,就可以得到具体的事件了。

 

下表是inotify对应的监控事件

IN_ACCESS  文件被访问(read())

IN_ATTRIB   文件元数据改变

IN_CLOSE_WRITE  关闭为写入而打开的文件

IN_CLOSE_NOWRITE  关闭以只读方式打开的文件

IN_CREATE   在受监控目录内创建文件/目录

IN_DELETE   在受监控目录内删除文件/目录

IN_DELETE_SELF  删除受监控目录/文件本身

IN_MODIFY   文件被修改

IN_MOVE_SELF   移除受监控文件/文件夹本身

IN_MOVED_FROM   文件移出到受监控目录之外

IN_MOVED_TO   将文件移入受监控目录

IN_OPEN  文件被打开

IN_ALL_EVENTS   上面事件的统称

IN_MOVE  IN_MOVED_FROM | IN_MOVED_TO的事件统称

IN_CLOSE   IN_CLOSE_WRITE|IN_CLOSE_NOWRITE的统称

IN_DONT_FOLLOW     不对符号链接解引用

IN_MASK_ADD 将事件追加到pathname的当前监控掩码

IN_ONESHOT  只监控pathname的一个事件

IN_ONLYDIR   pathname不为目录时会失败

IN_IGNORED   监控项为内核或应用程序所移除

IN_ISDIR    name中所返回的文件名为路径

IN_Q_OVERFLOW    事件队列溢出

IN_UNMOUNT    包含对象的文件操作系统遭卸载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值