inotify 是 Linux 内核提供的一个文件系统事件监控机制,允许应用程序监听文件系统中的事件(如文件的创建、删除、修改等)。这是一个强大的工具,可以帮助程序及时响应文件系统的变化。
inotify 的工作原理
-
初始化inotify实例:
使用 inotify_init() 或 inotify_init1() 函数创建一个 inotify 实例,该实例返回一个文件描述符。 -
添加监控项:
使用 inotify_add_watch() 函数将需要监控的文件或目录添加到 inotify 实例中。这个函数需要指定文件路径和需要监控的事件类型(如文件修改、创建、删除等)。 -
读取事件:
使用 read() 函数从 inotify 文件描述符中读取事件。读取到的事件数据会包含事件类型、监控的文件描述符以及事件相关的额外信息。 -
处理事件:
应用程序根据读取到的事件数据进行相应的处理,比如重新加载文件、触发某些操作等。 -
移除监控项:
使用 inotify_rm_watch() 函数移除不再需要监控的文件或目录。 -
关闭 inotify 实例:
使用 close() 函数关闭 inotify 文件描述符。 -
inotify 常用事件掩码
事件 | 描述 |
---|---|
IN_ACCESS | 文件被访问 |
IN_MODIFY | 文件被修改 |
IN_ATTRIB | 文件元数据被修改 |
IN_CLOSE_WRITE | 可写文件被关闭 |
IN_CLOSE_NOWRITE | 不可写文件被关闭 |
IN_OPEN | 文件被打开 |
IN_MOVED_FROM | 文件被移出 |
IN_MOVED_TO | 文件被移入 |
IN_CREATE | 文件或目录被创建 |
IN_DELETE | 文件或目录被删除 |
IN_DELETE_SELF | 自监控的文件被删除 |
IN_MOVE_SELF | 自监控的文件被移动 |
示例代码
以下是一个简单的使用 inotify 监控文件变化的 C 语言示例:
#include <sys/inotify.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define BUF_LEN (10 * (sizeof(struct inotify_event) + NAME_MAX + 1))
#define MONITOR_FILE "/path/to/monitor.txt"
int main() {
int inotify_fd = inotify_init();
if (inotify_fd == -1) {
perror("inotify_init");
exit(EXIT_FAILURE);
}
int wd = inotify_add_watch(inotify_fd, MONITOR_FILE, IN_MODIFY | IN_CREATE | IN_DELETE);
if (wd == -1) {
perror("inotify_add_watch");
close(inotify_fd);
exit(EXIT_FAILURE);
}
char buf[BUF_LEN] __attribute__((aligned(8)));
ssize_t numRead;
while (1) {
numRead = read(inotify_fd, buf, BUF_LEN);
if (numRead == 0) {
fprintf(stderr, "read() from inotify fd returned 0!");
exit(EXIT_FAILURE);
}
if (numRead == -1) {
perror("read");
exit(EXIT_FAILURE);
}
for (char *ptr = buf; ptr < buf + numRead; ) {
struct inotify_event *event = (struct inotify_event *) ptr;
if (event->mask & IN_MODIFY) {
printf("File modified: %s\n", event->name);
}
if (event->mask & IN_CREATE) {
printf("File created: %s\n", event->name);
}
if (event->mask & IN_DELETE) {
printf("File deleted: %s\n", event->name);
}
ptr += sizeof(struct inotify_event) + event->len;
}
}
close(wd);
close(inotify_fd);
return 0;
}