真正的手表描述符是啥? (Linux inotify 子系统)

Posted

技术标签:

【中文标题】真正的手表描述符是啥? (Linux inotify 子系统)【英文标题】:What are watch descriptors really ? (Linux inotify subsystem)真正的手表描述符是什么? (Linux inotify 子系统) 【发布时间】:2014-06-21 13:38:50 【问题描述】:

我目前正在使用 inotify() 系统在我的 C 代码中监视文件系统中某些目录的活动。

现在,使用这些东西之一的过程如下。你取一个整数(比如 event_notifier),使用 inotify_init() 把它变成一个 inotify 描述符,就像这样

event_notifier=inotify_init();

现在,假设我想监视多个目录上的事件。然后,我将通过这些目录将监视添加到这个 event_notifier

wd1 = inotify_add_watch(event_notifier,"/../path..to..directory1/../",IN_ALL_EVENTS);
wd2 = inotify_add_watch(event_notifier,"/../path..to..directory2/../",IN_ALL_EVENTS);
wd3 = inotify_add_watch(event_notifier,"/../path..to..directory3/../",IN_ALL_EVENTS);
                            . . . . 
wdn = inotify_add_watch(event_notifier,"/../path..to..directoryn/../",IN_ALL_EVENTS);

现在,我可以在多个目录中添加监视。这些调用中的每一个都返回一个“监视描述符”(上面的 wd1、wd2、wd3.. wdn)。每当任何目录中发生事件时,inotify 系统都会向 inotify 文件描述符 event_notifier 发送一个事件以及与该特定“监视目录”相对应的监视描述符(wd1,wd2...wdn)

当一个事件进来时,我可以读取 struct inotify_event 数组的 event_notifier。这个 inotify_event 结构有以下字段:

struct inotify_event  

  int wd; //Watch descriptor   
   ...  
  uint32_t len; //Size of 'name' field  
  char name[];  //null terminated name  

要读取事件,您只需这样做

read(event_notifier, buffer, sizeof(buffer))
struct inotify_event* event;
event=(struct inotify_event*)buffer; //Assuming only one event will occur

我有兴趣找出通知来自哪个目录。但是当我 stat() 监视描述符时,它什么也没给我

struct stat fileinfo;
fstat(event->wd, &fileinfo);
printf("\n Size of file is %l",fileinfo_st.size);

甚至 /proc/self/fd/event->fd 上的 readlink() 也没有产生任何文件名。

char filename[25]; 
readlink("/proc/self/fd/event-wd",filename,sizeof(filename));
printf("\n The filename is %s",filename);

我有两个问题:

1) 监视描述符到底指向什么? 它有什么好处? 2) 我如何知道通知来自哪个目录

【问题讨论】:

【参考方案1】:

监视描述符到底指向什么?有什么好处?

监视描述符不是文件系统对象或文件描述符。它是 inotify 子系统使用的资源描述符,用于将事件链接到 watched 资源,并让您可以在删除它们时指定某些手表。

您还应该注意,系统上可能的“打开”监视描述符的数量是有限的。您可以使用以下方法获得最大值:

cat  /proc/sys/fs/inotify/max_user_watches

如果您出于任何原因需要超过此值,您可以使用以下方法设置该值:

sudo sysctl -w fs.inotify.max_user_watches=XXXXXX

我如何知道通知来自哪个目录?

仅使用 inotify 扩展无法从事件结构中获取文件(目录)的完整路径。您的应用程序代码将需要特殊的查找表来存储监视描述符和完整路径名之间的链接。我在 php 中做过一次,因为我也觉得我需要它。您可以查看Github 上的代码。就像我说的,它是 PHP,但它可能有助于理解我在做什么。 (inotify 系统调用签名在 PHP 和 C 中是一样的)

【讨论】:

准确地说“手表描述符(单独)有利于删除手表”吗? 他们需要删除手表,将它们链接到完整的路径名:)(或任何元数据) 是的。但我们必须做链接部分。但是,就其本身而言,它们仅适用于移除手表。 :) 并非如此。没有它们,您将没有任何机会将事件链接到某个文件或元数据。由于 inotify 只为您提供基本名称,因此如果在不同目录中有多个具有相同名称的文件,您将不知道哪个文件已更改。【参考方案2】:

    手表描述符到底指向什么? 文件描述符不是指针,它是int。因此,它无法指向任何东西。 有什么用? 用于访问文件的文件描述符抽象指示符。使用 inotify,它是对虚拟文件的引用。

    内核维护一个包含进程文件详细信息的结构数组(文件描述符表)。文件描述符是该数组的索引。您的进程本身无法直接读取或写入文件描述符表。

    如何知道通知来自哪个目录? 您的应用程序负责将目录与句柄相关联。
    wd1 = inotify_add_watch(
       event_notifier,
       "/../path..to..directory1/../",
       IN_ALL_EVENTS
       );
    

【讨论】:

以上是关于真正的手表描述符是啥? (Linux inotify 子系统)的主要内容,如果未能解决你的问题,请参考以下文章

可测试辅助方法的访问修饰符是啥?

java命令行参数的默认访问修饰符是啥[关闭]

uint8_t 类型的 sscanf 占位符是啥?

Angular2:对于将在视图中访问的打字稿属性和函数的推荐访问修饰符是啥[关闭]

Java的类,方法,变量等等的默认修饰符是啥

levis手表中的CHRONO是啥意思