1、前言
inotify
是Linux内核提供的一种文件系统监控机制,可以用来监视文件系统的变化,如文件创建、删除、修改、移动等。通过inotify
,用户空间程序可以实时获取文件系统的变化事件,并做出相应的处理。
主要特点:
- 实时性:能够实时监控文件系统的变化。
- 高效性:采用事件驱动机制,不需要轮询文件系统。
- 灵活性:可以监控文件或目录的变化,支持递归监控
编程步骤:
- 调用
inotify_init
函数初始化一个inotify实例,获取一个inotify文件描述符。 - 使用
inotify_add_watch
函数向inotify实例中添加要监控的文件或目录。 - 调用
read
函数读取inotify实例中发生的事件。 - 根据事件类型做出相应的处理。
2、编程接口
2.1 inotify_init函数
初始化一个inotify实例,并返回一个inotify文件描述符。
int inotify_init(void);
返回值:
- 成功:返回一个新的inotify实例的文件描述符。
- 失败:返回-1,并设置errno以指示错误。
2.2 inotify_add_watch函数
用于向inotify
实例添加一个监视对象,并指定需要监视的事件类型。
int inotify_add_watch(int fd, const char *pathname, uint32_t mask);
入参:
fd
:inotify
实例的文件描述符。pathname
:要监视的文件或目录的路径。mask
:事件类型的掩码,可以使用OR
运算符组合多个事件类型。
返回值:
- 返回一个非负整数值作为监视描述符,用于唯一标识监视对象。
- 返回值为负数表示添加监视失败,错误码可通过
errno
获取。
2.3 inotify_rm_watch函数
从inotify实例中移除监控的文件或目录。
int inotify_rm_watch(int fd, int wd);
入参:
fd
:inotify
实例的文件描述符。wd
:要移除的监视描述符,即监视对象的标识符。
返回值:
- 返回0表示成功移除监视对象。
- 返回值为负数表示移除失败,错误码可通过
errno
获取。
2.4 struct inotify_event结构
通过read函数读取结果,结果的组织形式为struct inotify_event结构体:
struct inotify_event {
int wd; /* Watch descriptor */
uint32_t mask; /* Mask of events */
uint32_t cookie; /* Unique cookie associating related events (for rename(2)) */
uint32_t len; /* Size of 'name' field */
char name[]; /* Optional null-terminated name */
};
int wd
:监视描述符,表示事件所属的监视对象。uint32_t mask
:事件标志掩码,表示事件类型的位掩码,可以包括多个事件类型。uint32_t cookie
:关联事件的唯一标识符,用于关联相关的事件,比如重命名操作。uint32_t len
:文件名长度,表示name
字段的长度。char name[]
:可选的文件名字段,存储与事件相关的文件名。
mask
字段的事件类型:
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
:监视的文件或目录被移动。IN_ISDIR
:事件涉及的是目录而不是文件。IN_UNMOUNT
:监视的文件系统被卸载。IN_Q_OVERFLOW
:事件队列溢出。IN_IGNORED
:监视对象被移除或删除。IN_ONLYDIR
:只监视目录,不监视文件。IN_DONT_FOLLOW
:不要跟踪符号链接的目标。IN_EXCL_UNLINK
:监视对象必须是存在的。IN_MASK_ADD
:将新事件添加到现有事件掩码。IN_ONESHOT
:只监视一个事件,之后自动移除监视。IN_CLOSE
:文件被关闭(等同于IN_CLOSE_WRITE | IN_CLOSE_NOWRITE
)。IN_MOVE
:文件被移动(等同于IN_MOVED_FROM | IN_MOVED_TO
)。
3、编程测试
编写程序监控当前文件夹下文件的添加和删除操作,测试代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <sys/inotify.h>
#include <unistd.h>
#define EVENT_SIZE (sizeof(struct inotify_event))
#define BUF_LEN (1024 * (EVENT_SIZE + 16))
#define MONITOR_PATH "./"
int main()
{
int fd, wd;
char buffer[BUF_LEN];
fd = inotify_init();
if (fd < 0)
{
perror("inotify_init");
exit(EXIT_FAILURE);
}
wd = inotify_add_watch(fd, MONITOR_PATH, IN_ALL_EVENTS);
if (wd < 0)
{
perror("inotify_add_watch");
exit(EXIT_FAILURE);
}
printf("Monitoring directory %s ...\n", MONITOR_PATH);
while (1)
{
int length = read(fd, buffer, BUF_LEN);
if (length < 0)
{
perror("read");
exit(EXIT_FAILURE);
}
int i = 0;
while (i < length)
{
struct inotify_event *event = (struct inotify_event *)&buffer[i];
if (event->mask & IN_CREATE)
{
printf("File %s created\n", event->name);
}
else if (event->mask & IN_DELETE)
{
printf("File %s deleted\n", event->name);
}
i += EVENT_SIZE + event->len;
}
}
close(fd);
return 0;
}
测试结果如下,程序可以捕获到当前文件夹下文件的创建和删除信息:
4、总结
本文讲述了inotify的定义、编程步骤以及常用接口,并编写程序进行测试。