以递归方式监视目录以进行文件添加/修改/删除

时间:2013-12-17 21:21:26

标签: freebsd kqueue

我需要查看一个包含多个子目录的目录,每个子目录都有我需要监视文件添加,修改和删除的文件。

我找到了一些示例代码,并且必须稍微修改它以使其正常工作,但它并不能完全按照我的需要进行操作。它可以在目录(但不是子目录)中找到文件重命名或删除,但不会响应文件修改。

我使用Google搜索找到的方法是单独监控每个文件;但是,我有几十万个要监视的文件,并且每个文件描述符都可能是不明智的。

FreeBSD下有办法做我需要做的事吗?或者我必须找到替代解决方案吗?

#include <sys/types.h>
#include <sys/event.h>
#include <sys/time.h> 
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h> 

int main(void) {
   int f, kq, nev;
   struct kevent change;
   struct kevent event;

   kq = kqueue();
   if (kq == -1)
       perror("kqueue");

   f = open("/tmp/foo", O_RDONLY);
   if (f == -1)
       perror("open");

   EV_SET(&change, f, EVFILT_VNODE,
          EV_ADD | EV_ENABLE | EV_ONESHOT,
          NOTE_DELETE | NOTE_EXTEND | NOTE_WRITE | NOTE_ATTRIB,
          0, 0);

   for (;;) {
       nev = kevent(kq, &change, 1, &event, 1, NULL);
       if (nev == -1)
           perror("kevent");
       else if (nev > 0) {
           if (event.fflags & NOTE_DELETE) {
               printf("File deleted\n");
               break;
           }
           if (event.fflags & NOTE_EXTEND ||
               event.fflags & NOTE_WRITE)
               printf("File modified\n");
           if (event.fflags & NOTE_ATTRIB)
               printf("File attributes modified\n");
       }
   }

   close(kq);
   close(f);
   return EXIT_SUCCESS;
}

1 个答案:

答案 0 :(得分:1)

正如您所猜测的那样,kqueue不可扩展,因为您必须保留相关文件/目录的句柄,即使在O_RDONLY模式下也是如此。在Linux上,可以使用inotify来实现此目的(http://linux.die.net/man/7/inotify),但我相信这个内核功能没有FreeBSD端口!

如果你有时间和资源,你可以做的是查看BSD上的audit代码(http://www.freebsd.org/cgi/man.cgi?query=audit&sektion=4)并尝试为BSD编写inotify版本! O_O