2009-12-02 48 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