如何使用 inotify-rs 生成的 WatchDescriptor 结构将事件与生成它们的文件匹配?
How do I use the WatchDescriptor struct generated by inotify-rs to match events to files that generated them?
我正在使用 Inotify(通过 inotify-rs 包装器)来监视文件系统中的大量文件(不是目录)。
下面的inotify-rs方法returns一个WatchDescriptor
结构:
add_watch<P>(&mut self, path: P, mask: WatchMask) -> io::Result<WatchDescriptor>
where
P: AsRef<Path>
WatchDescriptor
是新类型结构:pub struct WatchDescriptor(RawFd);
其中 std::os::unix::io::RawFd
是类型 c_int
/f32
Inotify 子系统 returns 每次触发监视时 inotify_event
结构:
struct inotify_event {
int wd; /* Watch descriptor */
uint32_t mask; /* Mask describing event */
uint32_t cookie; /* Unique cookie associating related
events (for rename(2)) */
uint32_t len; /* Size of name field */
char name[]; /* Optional null-terminated name */
};
"Watch descriptor" int wd
与初始调用 add_watch()
生成的监视描述符相匹配
反过来,inotify-rs 包装器 returns 以下事件结构:
pub struct Event<'a> {
pub wd : WatchDescriptor,
pub mask : EventMask,
pub cookie: u32,
pub name : &'a OsStr,
}
我正在尝试使用 Event.wd
将事件与正在监视的文件列表中的文件相匹配。 (.name
只有 returns 一个文件名,如果事件在监视目录时触发)我尝试使用 HashMap
没有成功,因为结构 WatchDescriptor
没有派生Hash
特征。我试图 fork 这个箱子并自己实现它,但这打开了一个全新的蠕虫罐头。
最简单的方法应该是使用 Event.wd.0
来获得 c_int
/i32
但是我必须处理 error: field '0' of struct 'inotify::WatchDescriptor' is private
有没有一种简单的方法可以做到这一点,而不是重写包装器以按照我想要的方式运行,或者做一个 PR 并等待它被合并?
我考虑过为每个正在观看的文件创建一个 Inotify
,但是在可以观看数百个文件的情况下,这将非常昂贵。
此库存在一些重大问题:
- 表示 inotify 监视描述符的类型选择不当。 Inotify 监视描述符是 而不是 Unix 文件描述符,它们只是一些整数,每个 inotify 文件描述符的作用域。这本身并不是一个缺陷,但我当然会将其视为危险信号。
- 如上所述,inotify 监视描述符值的范围是每个父 inotify 文件描述符。这使得在
WatchDescriptor
上使用 [derive(Eq)]
非常值得怀疑。看起来像一个直接的错误。
- 没有什么可以确保在关闭 inotify 描述符之前关闭 inotify watches。没有什么可以确保监视描述符不会在您的背后被重用(它们可以在监视描述符编号回绕后重用)。这些问题可能不会立即困扰您,但是……IMO,应该声明整个 inotify-rs
unsafe
。它不会在 inotify 之上添加任何实际的安全性,只是一些糖和无意义的包装。它甚至没有为监视描述符实现 Drop
!
- 该库没有突出 inotify 的主要陷阱:事件队列溢出,
IN_IGNORED
和硬链接共享相同的 inode(以及相同的 inotify 监视描述符!)
我建议您仔细阅读 inotify 文档并在必要时编写自己的包装器。这个库不会为你省去任何麻烦。
我正在使用 Inotify(通过 inotify-rs 包装器)来监视文件系统中的大量文件(不是目录)。
下面的inotify-rs方法returns一个WatchDescriptor
结构:
add_watch<P>(&mut self, path: P, mask: WatchMask) -> io::Result<WatchDescriptor>
where
P: AsRef<Path>
WatchDescriptor
是新类型结构:pub struct WatchDescriptor(RawFd);
其中 std::os::unix::io::RawFd
是类型 c_int
/f32
Inotify 子系统 returns 每次触发监视时 inotify_event
结构:
struct inotify_event {
int wd; /* Watch descriptor */
uint32_t mask; /* Mask describing event */
uint32_t cookie; /* Unique cookie associating related
events (for rename(2)) */
uint32_t len; /* Size of name field */
char name[]; /* Optional null-terminated name */
};
"Watch descriptor" int wd
与初始调用 add_watch()
反过来,inotify-rs 包装器 returns 以下事件结构:
pub struct Event<'a> {
pub wd : WatchDescriptor,
pub mask : EventMask,
pub cookie: u32,
pub name : &'a OsStr,
}
我正在尝试使用 Event.wd
将事件与正在监视的文件列表中的文件相匹配。 (.name
只有 returns 一个文件名,如果事件在监视目录时触发)我尝试使用 HashMap
没有成功,因为结构 WatchDescriptor
没有派生Hash
特征。我试图 fork 这个箱子并自己实现它,但这打开了一个全新的蠕虫罐头。
最简单的方法应该是使用 Event.wd.0
来获得 c_int
/i32
但是我必须处理 error: field '0' of struct 'inotify::WatchDescriptor' is private
有没有一种简单的方法可以做到这一点,而不是重写包装器以按照我想要的方式运行,或者做一个 PR 并等待它被合并?
我考虑过为每个正在观看的文件创建一个 Inotify
,但是在可以观看数百个文件的情况下,这将非常昂贵。
此库存在一些重大问题:
- 表示 inotify 监视描述符的类型选择不当。 Inotify 监视描述符是 而不是 Unix 文件描述符,它们只是一些整数,每个 inotify 文件描述符的作用域。这本身并不是一个缺陷,但我当然会将其视为危险信号。
- 如上所述,inotify 监视描述符值的范围是每个父 inotify 文件描述符。这使得在
WatchDescriptor
上使用[derive(Eq)]
非常值得怀疑。看起来像一个直接的错误。 - 没有什么可以确保在关闭 inotify 描述符之前关闭 inotify watches。没有什么可以确保监视描述符不会在您的背后被重用(它们可以在监视描述符编号回绕后重用)。这些问题可能不会立即困扰您,但是……IMO,应该声明整个 inotify-rs
unsafe
。它不会在 inotify 之上添加任何实际的安全性,只是一些糖和无意义的包装。它甚至没有为监视描述符实现Drop
! - 该库没有突出 inotify 的主要陷阱:事件队列溢出,
IN_IGNORED
和硬链接共享相同的 inode(以及相同的 inotify 监视描述符!)
我建议您仔细阅读 inotify 文档并在必要时编写自己的包装器。这个库不会为你省去任何麻烦。