2009-12-02 53 views
16

fanotify,建立在fsnotify之上,应该取代inotify,它代替dnotify。是否有一些好的编程示例或现有实用程序使用fanotify来监视文件系统中的更改? fanotify提供多少细节?如何编写Linux新的`fanotify`文件系统监控功能?

+0

仅供参考:Fanotify有一个错误。 http://stackoverflow.com/questions/7566755/multi-thread-opening-file-hangs-when-fanotify-is-on这里是一个补丁。 http://marc.info/?l=linux-kernel&m=131822913806350&w=2 – user377808

回答

6

我刚刚了解到fanotify,它似乎非常好。非常漂亮的界面!

它不在Linus树中,但我猜它会在Linux 2.6.33和之前进行测试(我注意到今天在LKML中有一些补丁)。在最初的补丁中,他们宣布了一个GIT树,因此您可以从那里构建测试内核。你也可能会发现测试混帐树。

我找不到使用它的工具,但我猜他们很快就会来。

有一个例子在这里,在邮件的末尾:

http://lwn.net/Articles/339253/

如果你在这个新功能很感兴趣,你可能要监控的Linux内核邮件列表和互动那里。您也可以等到公用设施发布或开发您自己的设备。

关于细节,似乎fanotify比inotify提供更少的事件。我想这可能会在未来发生变化,但由于这是一项全新的开发功能,因此我现在可以说的并不多。

+1

最后fanotify进入2.6.36 –

16

This LWN article经常被引用为fanotify文档的来源。但说明似乎已过时。 fanotify不再使用套接字连接。相反,有两个新的libc函数包装系统调用,在sys/fanotify.h中声明。一个叫fanotify_init,另一个叫fanotify_mark。在撰写本文时,这些系统调用仍包含在list of missing manual pages中。但是,这些手册页有mail containing drafts。通过这些手册页的组合,查看标题,以及一些试验和错误,你应该能够做到这一点。

看来,一些原本设想fanotify的功能是在时尚不再suipported。例如,LWN文章描述了一个FAN_GLOBAL_LISTENER标志,这将标志着隐含整个文件系统树,除非部分是明确地无人盯防。目前的接口有没有这样的规定,但可以使用下面的标记来实现类似的结果:

fanotify_mark(fan, 
       FAN_MARK_ADD | FAN_MARK_MOUNT, 
       FAN_OPEN | FAN_EVENT_ON_CHILD, 
       AT_FDCWD, "/") 

凡inotify事件提供路径访问的对象作为事件的一部分,fanotify打开文件描述符为它。为了将此描述符转换为路径名称,可以使用proc文件系统中的相应条目,如here所述。

举个简单的例子只是打印每一个打开的文件的名称:

#include <fcntl.h> 
#include <limits.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <sys/fanotify.h> 
#include <sys/stat.h> 
#include <sys/types.h> 
#define CHK(expr, errcode) if((expr)==errcode) perror(#expr), exit(EXIT_FAILURE) 
int main(int argc, char** argv) { 
    int fan; 
    char buf[4096]; 
    char fdpath[32]; 
    char path[PATH_MAX + 1]; 
    ssize_t buflen, linklen; 
    struct fanotify_event_metadata *metadata; 
    CHK(fan = fanotify_init(FAN_CLASS_NOTIF, O_RDONLY), -1); 
    CHK(fanotify_mark(fan, FAN_MARK_ADD | FAN_MARK_MOUNT, 
        FAN_OPEN | FAN_EVENT_ON_CHILD, AT_FDCWD, "/"), -1); 
    for (;;) { 
    CHK(buflen = read(fan, buf, sizeof(buf)), -1); 
    metadata = (struct fanotify_event_metadata*)&buf; 
    while(FAN_EVENT_OK(metadata, buflen)) { 
     if (metadata->mask & FAN_Q_OVERFLOW) { 
     printf("Queue overflow!\n"); 
     continue; 
     } 
     sprintf(fdpath, "/proc/self/fd/%d", metadata->fd); 
     CHK(linklen = readlink(fdpath, path, sizeof(path) - 1), -1); 
     path[linklen] = '\0'; 
     printf("%s opened by process %d.\n", path, (int)metadata->pid); 
     close(metadata->fd); 
     metadata = FAN_EVENT_NEXT(metadata, buflen); 
    } 
    } 
} 
11