如何为 Linux 的新“fanotify”文件系统监控功能进行编程?

发布于 2024-08-13 16:46:05 字数 199 浏览 9 评论 0原文

fanotify 构建于 fsnotify 之上,应该取代 inotify,后者取代了 dnotify。是否有一些好的编程示例或现有实用程序使用 fanotify 来监视文件系统中的更改? fanotify 提供了多少详细信息?

fanotify, built on top of fsnotify, is supposed to replace inotify which replaced dnotify. Are there some good programming examples or existing utilities that use fanotify to watch for changes in a filesystem? How much detail does fanotify provide?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

垂暮老矣 2024-08-20 16:46:05

这篇 LWN 文章经常被引用作为 fanotify 的文档来源。但那里的描述似乎已经过时了。 fanotify 不再使用套接字连接工作。相反,有两个新的 libc 函数包装了系统调用,在 sys/fanotify.h 中声明。一个称为 fanotify_init,另一个称为 fanotify_mark。在撰写本文时,这些系统调用仍然包含在缺失手册页列表。然而,有一个包含这些手册页草稿的邮件。通过结合这些手册页,查看相关标题,并进行一些尝试和错误,您应该能够实现这一点。

最初为 fanotify 设想的一些功能似乎不再以这种方式支持。例如,LWN 文章描述了一个 FAN_GLOBAL_LISTENER 标志,该标志将隐式标记整个文件系统树,除非明确未标记某些部分。当前接口没有这样的规定,但是使用以下标记可以实现类似的结果:

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

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

这是一个简单的示例,它仅打印每个打开的文件的名称:

#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);
    }
  }
}

This LWN article is often quoted as a source of documentation for fanotify. But the description there appears to be out of date. fanotify no longer works using a socket connection. Instead, there are two new libc functions wrapping syscalls, declared in sys/fanotify.h. One is called fanotify_init, the other is fanotify_mark. At the time of this writing, these syscalls are still included in the list of missing manual pages. There is, however, a mail containing drafts for these manual pages. With a combination of these man pages, a look at the headers in question, and a bit of trial and error, you should be able to get this going.

It seems that some of the functionality originally envisioned for fanotify is no longer suipported in that fashion. For example, the LWN article describes a FAN_GLOBAL_LISTENER flag which will implicitely mark the whole filesystem tree unless parts are explicitely unmarked. The current interface has no such provision, but a similar result can be achieved using the following mark:

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

Where inotify events provide the path to the accessed object as part of the event, fanotify opens a file descriptor for it. In order to turn this descriptor into a path name, the corresponding entry from the proc file system can be used, as described here.

Here is a simple example which simply prints the name of every opened file:

#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);
    }
  }
}
韬韬不绝 2024-08-20 16:46:05

我刚刚了解了 fanotify,它看起来非常好。非常好的界面!

它还不在 Linus 树中,但我想它会在 Linux 2.6.33 及之前的版本中到达那里进行测试(我今天在 LKML 中注意到了一些补丁)。在原始补丁中,他们宣布了一个 GIT 树,因此您可以从那里构建一个测试内核。您可能还会发现测试 git 树。

我找不到使用它的实用程序,但我想它们很快就会出现。

电子邮件末尾有一个示例:

http://lwn.net/Articles/339253/< /a>

如果您确实对这个新功能感兴趣,您可能想要监视 Linux 内核邮件列表并在那里进行交互。您也可以等到实用程序发布或开发自己的实用程序。

关于细节,似乎 fanotify 提供的事件比 inotify 少。我想这将来可能会改变,但由于这是正在开发中的全新功能,所以我现在对此无话可说。

I just learned about fanotify and it seems very nice. Very nice interface!

It is not in the Linus tree yet but I guess it will get there for Linux 2.6.33 and before for testing (I noticed some patches today in LKML). In the original patch they announce a GIT tree thus you might be able to build a testing kernel from there. You might also find testing git trees.

I couldn't find utilities that use it but I guess they'll come soon.

There is an example here, at the end of the email:

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

If you are really interested in this new feature you might want to monitor the Linux Kernel Mailing List and interact there. You can also wait until the utilities are released or develop your own.

About the detail, it seems fanotify provides less events than inotify. I guess this might change in the future but since this is a brand new feature in development there is not much I can say about it now.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文