使用 inotify 監視某資料夾的一舉一動

在 Linux 下監視某個資料夾的變化,有很多種方法,可以土法煉鋼的定時去掃描、檢查修改時間,也可以去將檔案一一開啟比對,不過往往這些過程,都伴隨著大量且多餘的 IO 存取。對此,使用 inotify 就顯得比較方便且有效率。自從 hal 的出現後,我們已經可以使用 inotify 去攔截某個檔案或資料夾一舉一動的 event,若是整合 GLib ,短短數行即可實作出來。
#include <glib.h>
#include <sys/inotify.h>
#include <sys/types.h>
#include <errno.h>

void inotify_events_io_func(GIOChannel *channel, GIOCondition condition, gpointer data)
{
char buf[1024];
struct inotify_event *event;
gint index = 0;
gint len = 0;
gint fd = g_io_channel_unix_get_fd(channel);

while(((len = read(fd, &buf, sizeof(buf))) < 0) && (errno == EINTR));

while(index<len) {
event = (struct inotify_event*)(buf+index);

/* read events */
switch(event->mask)
{
case IN_MODIFY:
printf("MODIFY\n");
break;
case IN_CREATE
printf("CREATE\n");
break;
case IN_DELETE:
printf("DELETE\n");
break;
}

index += sizeof(struct inotify_event) + event->len;
}
}

int main(int argc, char* argv[])
{
GMainLoop *loop;
GIOChannel *channel;
gint ino_fd = 0;
gint ino_wd = 0;

/* inotify */
ino_fd = inotify_init();
ino_wd = inotify_add_watch(ino_fd, "/usr/share/applications", IN_MODIFY | IN_CREATE | IN_DELETE);
channel = g_io_channel_unix_new(ino_fd);
g_io_add_watch(channel, G_IO_IN, (GIOFunc)inotify_events_io_func, (gpointer)NULL);

loop = g_main_loop_new(NULL, FALSE);
g_main_loop_run(loop);
}

該範例將會監聽 /usr/share/applications 資料夾內的檔案更動 event ,並印出來。因為該資料夾是 FreeDesktop.org Spec 中用來記錄桌面 application 資訊的,當安裝或是刪除軟體時,即會收到檔案新增或刪除的 event。

留言

  1. 但是只對當前的目錄,如何對二級目錄進行觀察?

    回覆刪除
  2. 我尚未研究過此課題,也許可將該目錄下之目錄一一列出,再監聽其 event。

    回覆刪除
  3. 純路過,
    在下前陣子剛好也有在找file activity monitoring這方面的solution, 順便分享一下結果:
    對於一次要能monitor整個filesystem上的activity, 這裡有一個名為fschange的kernel side solution:

    http://stefan.buettcher.org/cs/fschange/index.html

    網頁中提供的 'inotify->fschange Daemon' 實際上就是如Fred所提, 用列舉的方式去註冊所有的directories 的 inotify event, 來演譯fschange最後所要達到的成果

    回覆刪除

張貼留言

這個網誌中的熱門文章

有趣的邏輯問題:是誰在說謊

Web 技術中的 Session 是什麼?

淺談 USB 通訊架構之定義(一)

淺談 USB 通訊架構之定義(二)

Reverse SSH Tunnel 反向打洞實錄