一、inotify是什么
inotify是Linux内核用来通知用户空间程序文件系统发生变化的一种机制。
二、inotify的使用方法
inotify 的使用很简单,具体如下。
1、首先,调用 inotify_init 创建 inotify 实例
int inotify_init(void);
2、调用 inotify_add_watch 添加一个 watch
int inotify_add_watch(int fd, const char *path, uint32_t mask);
- fd:inotify_init() 返回的文件描述符
- path:被监视的目标的路径名(即文件名或目录名)。如果监听目录,则该目录下的所有文件发生的事件都会被监听
- mask:事件掩码,在头文件 linux/inotify.h 中定义了每一位代表的事件
- 调用成功后,返回被监听文件或目录的描述符 wd
可以使用同样的方式来修改事件掩码,即改变希望被通知的 inotify 事件。
inotify 主要的事件掩码(mask)定义如下:
#define IN_ACCESS 0x00000001 /* File was accessed */
#define IN_MODIFY 0x00000002 /* File was modified */
#define IN_ATTRIB 0x00000004 /* Metadata changed */
#define IN_CLOSE_WRITE 0x00000008 /* Writtable file was closed */
#define IN_CLOSE_NOWRITE 0x00000010 /* Unwrittable file closed */
#define IN_OPEN 0x00000020 /* File was opened */
#define IN_MOVED_FROM 0x00000040 /* File was moved from X */
#define IN_MOVED_TO 0x00000080 /* File was moved to Y */
#define IN_CREATE 0x00000100 /* Subfile was created */
#define IN_DELETE 0x00000200 /* Subfile was deleted */
#define IN_DELETE_SELF 0x00000400 /* Self was deleted */
#define IN_MOVE_SELF 0x00000800 /* Self was moved */
3、读取 inotify 事件
inotity 并没有提供特定的接口来获取被监听的文件或目录的变动事件,而是通过通用的 read 函数来读取,我们来看看 read 函数的原型:
int read(int fd, void *events, size_t len);
- fd 是 inotify_init() 返回的文件描述符
- events 是存放 inotify 事件的缓冲区,一般指定为 inotify_event 结构的数组
- len为缓冲区的大小,至少大于 inotify_event 的大小
inotify_event 结构的定义如下:
struct inotify_event {
__s32 wd; /* watch descriptor */
__u32 mask; /* watch mask */
__u32 cookie; /* cookie to synchronize two events */
__u32 len; /* length (including nulls) of name */
char name[0]; /* stub for possible name */
};
- wd 为被监视目标的 watch 描述符
- mask 为事件掩码
- len 为 name字符串的长度
- name 为被监视目标的路径名,文件名是变长的,它实际紧跟在该结构的后面,文件名将被 0 填充以使下一个事件结构能够 4 字节对齐。注意,len 也把填充字节数统计在内。
4、调用 inotify_rm_watch 删除添某个 watch
int inotify_rm_watch(int fd, uint32_t wd);
- fd 是 inotify_init() 返回的文件描述符
- wd 是 inotify_add_watch() 返回的 watch 描述符
5、调用 close(fd) 删除所有的 watch ,并做必要的清理。
三、使用实例
#define EVENTS_BUF_SIZE 4096
int main(int argc, char const *argv[])
{
int fd;
int nbytes, offset;
char events[EVENTS_BUF_SIZE];
struct inotify_event *event;
int result = 0;
// 创建 inotify 句柄
fd = inotify_init();
if (fd < 0) {
printf("Failed to initalize inotify\n");
return -1;
}
// 添加要监听的文件或者目录, 监听所有事件
if (inotify_add_watch(fd, argv[1], IN_ALL_EVENTS) == -1) {
printf("Failed to add file or directory watch\n");
result = -1;
goto out;
}
for (;;) {
memset(events, 0, sizeof(events));
// 读取 inotify 事件
nbytes = read(fd, events, sizeof(events));
if (nbytes <= 0) {
printf("Failed to read events\n");
continue;
}
// 开始处理 inotify 事件
for (offset = 0; offset < nbytes; ) {
// 获取事件的指针
event = (struct inotify_event *)&events[offset];
//处理 inotify 事件
......
// 获取下一个事件的偏移量
offset += sizeof(struct inotify_event) + event->len;
}
}
out:
close(fd);
return result;
}