`

inotify只能监控单层目录变化,不能监控子目录中的变化情况。

阅读更多
inotify只能监控单层目录变化,不能监控子目录中的变化情况。
如果需要监控子目录,需要在调用inotify_add_watch(int fd, char *dir, int mask):int建立监控时,递归建立子目录的监控,伪代码如下
void addwatch(int fd, char *dir, int mask)
{
    wd = inotify_add_watch(fd, dir, mask);
    向目录集合加入(wd, dir);
    for (dir下所有的子目录subdir)
        addwatch(fd, subdir, mask);
}
这样就可以得到一个目录集合,其中每一个wd对应一个子目录。
当你调用read获取信息时,可以得到一个下面的结构体
struct inotify_event
{
  int wd;               /* Watch descriptor.  */
  uint32_t mask;        /* Watch mask.  */
  uint32_t cookie;      /* Cookie to synchronize two events.  */
  uint32_t len;         /* Length (including NULs) of name.  */
  char name __flexarr;  /* Name.  */
};
其中,通过event->wd和刚才记录的目录集合可以知道变动的具体子目录。
event->name为具体的文件名称。
event->name是一个char name[0]形式的桩指针,具体的name占据的长度可以由event->len得出

我的监控部分代码如下:
enum {EVENT_SIZE = sizeof(struct inotify_event)};
enum {BUF_SIZE = (EVENT_SIZE + 16) << 10};
void watch_mon(int fd)
{
        int i, length;
        void *buf;
        struct inotify_event *event;
        buf = malloc(BUF_SIZE);

        while ((length = read(fd, buf, BUF_SIZE)) >= 0)
        {
                i = 0;
                while (i < length)
                {
                        event = buf + i;
                        if (event->len)
                                具体处理函数(event);
                        i += EVENT_SIZE + event->len;
                }
        }
        close(fd);
        exit(1);
}
在你的具体处理函数中,通过wd辨识子目录,通过name辨识文件

这是利用C++STLmap写的一个范例,可以监视当前目录下(含子目录)的变化,创建,删除过程(新建立的目录不能监视,只能通过监视到创建新目录的事件后重新初始化监视表)
新版1.1.0,可以监视创建的子目录,方法是,当do_action探测到新目录创建的动作时,调用inotify_add_watch追加新的监视
/*
    Copyright (C) 2010-2011 LIU An (SuperHacker@china.com.cn)

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <unistd.h>
#include <sys/types.h>
#include <sys/inotify.h>
#include <errno.h>
#include <dirent.h>

#include <map>
#include <string>
using namespace std;

void addwatch(int, char*, int);
static int filter_action(uint32_t mask);
int watch_init(int mask, char *root);
void addwatch(int fd, char *dir, int mask);
static void do_action(int fd, struct inotify_event *event);
void watch_mon(int fd);
static void send_mess(char *name, char *act, int ewd);
void append_dir(int fd, struct inotify_event *event, int mask);

map<int, string> dirset;

enum{MASK = IN_MODIFY | IN_CREATE | IN_DELETE};

int main(int argc, char **argv)
{
        int fd;
        if (argc != 2)
        {
                fprintf(stderr, "Usage: %s dir\n", argv[0]);
                exit(1);
        }

        fd = watch_init(MASK, argv[1]);
        watch_mon(fd);

        return 0;
}

int watch_init(int mask, char *root)
{
        int i, fd;

        if ((fd = inotify_init()) < 0)
                perror("inotify_init");
        addwatch(fd, root, mask);
        return fd;
}

void addwatch(int fd, char *dir, int mask)
{
        int wd;
        char subdir[512];
        DIR *odir;
        struct dirent *dent;

        if ((odir = opendir(dir)) == NULL)
        {
                perror("fail to open root dir");
                exit(1);
        }
        wd = inotify_add_watch(fd, dir, mask);
        dirset.insert(make_pair(wd, string(dir)));

        errno = 0;
        while ((dent = readdir(odir)) != NULL)
        {
                if (strcmp(dent->d_name, ".") == 0
                        || strcmp(dent->d_name, "..") == 0)
                        continue;
                if (dent->d_type == DT_DIR)
                {
                        sprintf(subdir, "%s/%s", dir, dent->d_name);
                        addwatch(fd, subdir, mask);
                }
        }

        if (errno != 0)
        {
                perror("fail to read dir");
                exit(1);
        }

        closedir (odir);
}

enum {EVENT_SIZE = sizeof(struct inotify_event)};
enum {BUF_SIZE = (EVENT_SIZE + 16) << 10};

void watch_mon(int fd)
{
        int i, length;
        void *buf;
        struct inotify_event *event;
        buf = malloc(BUF_SIZE);

        while ((length = read(fd, buf, BUF_SIZE)) >= 0)
        {
                i = 0;
                while (i < length)
                {
                        event = (struct inotify_event*)(buf + i);
                        if (event->len)
                                do_action(fd, event);
                        i += EVENT_SIZE + event->len;
                }
        }
        close(fd);
        exit(1);
}

static char action[][10] =
{
        "modified",
        "accessed",
        "created",
        "removed"
};

enum{NEWDIR = IN_CREATE | IN_ISDIR};

static void do_action(int fd, struct inotify_event *event)
{
        int ia, i;

        if ((ia = filter_action(event->mask)) < 0)
                return;

        if ((event->mask & NEWDIR) == NEWDIR)
                append_dir(fd, event, MASK);

        send_mess(event->name, action[ia], event->wd);
}

void append_dir(int fd, struct inotify_event *event, int mask)
{
        char ndir[512];
        int wd;

        sprintf(ndir, "%s/%s", dirset.find(event->wd)->second.c_str(),
                        event->name);
        wd = inotify_add_watch(fd, ndir, mask);
        dirset.insert(make_pair(wd, string(ndir)));
}

static int filter_action(uint32_t mask)
{
        if (mask & IN_MODIFY)
                return 0;
        if (mask & IN_ACCESS)
                return 1;
        if (mask & IN_CREATE)
                return 2;
        if (mask & IN_DELETE)
                return 3;
        return -1;
}

static void send_mess(char *name, char *act, int ewd)
{
        char format[] = "%s was %s.\n";
        char file[512];

        sprintf(file, "%s/%s", dirset.find(ewd)->second.c_str(), name);

        printf(format, file, act);
}

参考资料是我们作业的提交,没有考虑递归创建子目录监控的问题。
参考资料:http://59.67.33.217/homeworkref/sources/2010-2011-1.2008.software.os.inotify.tar.xz
转: http://zhidao.baidu.com/question/218179319.com
分享到:
评论

相关推荐

    用inotify监视文件目录变化

    inotify是一种Linux 内核提供的文件系统事件通知机制,可以监视文件目录的变化,实时地通知应用程序文件系统中的变化。下面是使用inotify监视文件目录变化的知识点: 1. 什么是inotify? inotify是Linux 内核提供...

    FTP客户端,通过inotify机制,可实现对特定目录下的文件生成情况进行监控,当有文件生成后自动上传到FTP服务器

    在本文中,我们将深入探讨如何利用C语言编程实现一个FTP客户端,并结合inotify机制来实现实时监控特定目录下新生成的文件,并在文件创建后自动上传到FTP服务器。 首先,我们需要理解FTP(File Transfer Protocol)...

    inotify linux 的文件夹监视

    这是监视文件夹变化的程序,指定监视的文件夹类型

    Linux inotify

    inotify 实现机制中,每一个文件或者目录在内核中都有对应的 inode 结构,inotify 在 inode 结构后添加了两个字段 inotify_watch 和 inotify_device。inotify_device 结构体在 inotify_init() 时创建,inotify_watch...

    使用Inotify 监控目录与文件的方法详解

    以下是关于使用 Inotify 监控目录与文件的一些关键知识点: 1. **初始化 Inotify**: `inotify_init()` 函数用于初始化一个 Inotify 实例,返回一个文件描述符(fd),后续的所有操作都将基于这个描述符进行。 2....

    linux下监控文件夹内变化

    总的来说,这个项目为你提供了一个实际应用Inotify机制的示例,通过学习和实践,不仅可以深入理解Inotify的工作原理,还能掌握在Linux环境下使用C语言编程监控文件系统变化的技能。记得参考提供的文档和说明,以便更...

    如何使用inotify编写监控程序.txt

    如何使用inotify编写监控程序

    iNotify c语言 demo

    在这个“iNotify c语言 demo”中,程序启动后会监控当前目录下的"src"子目录。当你对"src"内的文件进行任何操作时,例如创建新文件、修改现有文件、删除文件或移动文件,程序都会检测到这些变化,并显示相应的监控...

    inotify用法详解

    ### inotify 用法详解:实时监控文件系统变化的关键技术 在Linux环境下,inotify提供了一种高效且灵活的方式来监控文件系统的变化,如文件或目录的创建、删除、修改等事件。这一机制对于自动化脚本编写、日志监控...

    inotify文件监控工具 适用于 EL6 & EL7

    inotify 是内核2.6.13引入的一个新功能,为用户监控文件系统提供强大的支持。一般配合rsync使用。实现服务器之间实时同步备份。 此版本适用于EL6 或者 EL7 版本。 本人使用CentOS6和CentOS7。

    目录监控 监控文件夹

    综上,目录监控是IT运维中不可或缺的一部分,通过有效的监控文件夹,我们可以更好地保障系统安全,提升运维效率,同时也能为问题解决提供重要线索。在实际应用中,选择合适的工具和方法,结合业务需求,定制化的目录...

    用inotify+rsrnc实现linux文件及目录的监控和同步

    在Linux系统中,实时监控文件或目录的变化是一项重要的任务,特别是在开发、运维或者自动化场景下。`inotify`是Linux内核提供的一种高效的通知机制,它允许应用程序监听文件系统的事件,如创建、删除、修改等。结合`...

    rsync+inotify实现服务器之间目录文件实时同步

    该脚本通过 inotifywait 监控 `$src` 目录下的文件变化,并在发生指定事件时执行 rsync 命令将变化同步到目标主机的相应目录。 4. **日志管理**: - 日志文件建议不要放置在被监控的目录中,以免造成循环同步...

    监控目录变化

    在IT行业中,监控目录变化是一项重要的任务,尤其是在系统管理和日志跟踪、自动化脚本执行以及数据同步场景下。本文将详细解析如何使用VC(Visual C++)编程来实现这一功能,以及这一技术在操作系统文件监控中的应用...

    rsync+inotify实现服务器之间文件实时同步

    rsync+inotify是一种实现服务器之间文件实时同步的解决方案,该方案可以实时监控文件系统的变化,并将变化同步到备份服务器中,保障数据的一致性和实时性。 rsync是一种文件同步工具,可以实现触发式的文件同步,但...

    inotify-tools软件包

    `inotifywait`是`inotify-tools`中用于实时监控文件或目录变化的命令。它的基本用法是监控指定的文件或目录,并在发生指定的事件时退出或执行预定义的命令。例如,你可以使用`inotifywait`来监视一个目录,当有新的...

    Python中使用Inotify监控文件实例

    在Python中使用Inotify监控文件,通常是指利用Linux下的inotify机制来监控文件系统的变化,例如文件的创建、删除和修改等操作。Inotify是一种强大的文件系统事件监控机制,它使得程序能够异步地接收关于文件系统变化...

    inotify-tools-3.14.tar.gz工具源码包

    2.6.13起,加入了Inotify支持,通过Inotify可以监控文件系统中添加、删除,修改、移动等各种事件,利用这个内核接口,第三方软件就可以监控文件系统下文件的各种变化情况,而inotify-tools正是实施这样监控的软件。...

    inotify-tools-3.14源码包

    例如,当监控目录有新文件生成时,可以立即触发`rsync`进行备份: ```bash inotifywait -m /source/directory -e close_write | while read path action file; do rsync -avz "$path$file" /backup/directory; done...

Global site tag (gtag.js) - Google Analytics