自从Linux kernel 2.6.13起,inotify以作为内核的一部份,同时需要glibc 2.4以上版本。
1. 相关函数
inotify_init() - 创建一个inotify实例inotify_add_watch(int fd, const char *pathname, uint32_t mask) - 加入文件或目录到inotify进行监测
inotify_rm_watch(int fd, int wd) - 移除一个watcher
2. 相关结构
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 */ };
3. Mask
适用于 inotify_add_watch mask 与 read 返回的inotify_event中maskIN_ACCESS | 文件被访问 |
IN_ATTRIB | 文件属性发生变化 |
IN_CLOSE_WRITE | 以write方式打开文件并关闭 |
IN_CLOSE_NOWRITE | 以非write方式打开文件并关闭 |
IN_CREATE | 文件或目录被创建 |
IN_DELETE | 文件或目录被删除(被监测的文件夹A中B文件被删除) |
IN_DELETE_SELF | 被监测的文件或目录被删除(被监测的文件夹A被删除) |
IN_MODIFY | 文件被修改 |
IN_MOVE_SELF | 被监测的文件或目录移动 |
IN_MOVED_FROM | 文件移出被监测的目录 |
IN_MOVED_TO | 文件移入被监测的目录 |
IN_OPEN | 文件被打开 |
上述flag的集合 | |
IN_ALL_EVENTS | 以上所有flag的集合 |
IN_MOVE | IN_MOVED_TO|IN_MOVED_FROM |
IN_CLOSE | IN_CLOSE_WRITE|IN_CLOSE_NOWRITE |
不常用的flag | |
IN_DONT_FOLLOW | 不follow符号链接 (since 2.6.15) |
IN_EXCL_UNLINK | 当文件从监测目中unlink后,则不再报告该文件的相关event,比如监控/tmp使用 (since 2.6.36) |
IN_MASK_ADD | 追打MASK到被监测的pathname |
IN_ONESHOT | 只监测一次 |
IN_ONLYDIR | 只监测目录 |
IN_IGNORED | inotify_rm_watch,文件被删除或者文件系统被umount |
IN_ISDIR | 发生事件的是一个目录 |
IN_Q_OVERFLOW | Event队列溢出 |
IN_UNMOUNT | 文件系统unmount |
4. 例子
用途:监测指定文件或目录(或不指定则为当前目录)的一切动作。使用:inotify [文件或目录]
- #include <unistd.h>
- #include <sys/inotify.h>
- #include <stdio.h>
- #include <error.h>
- #include <errno.h>
- #include <string.h>
- #define ERROR(text) error(1, errno, "%s", text)
- struct EventMask {
- int flag;
- const char *name;
- };
- int freadsome(void *dest, size_t remain, FILE *file)
- {
- char *offset = (char*)dest;
- while (remain) {
- int n = fread(offset, 1, remain, file);
- if (n==0) {
- return -1;
- }
- remain -= n;
- offset += n;
- }
- return 0;
- }
- int main(int argc, char *argv[])
- {
- const char *target;
- if (argc == 1) {
- target = ".";
- } else {
- target = argv[1];
- }
- EventMask event_masks[] = {
- {IN_ACCESS , "IN_ACCESS"} ,
- {IN_ATTRIB , "IN_ATTRIB"} ,
- {IN_CLOSE_WRITE , "IN_CLOSE_WRITE"} ,
- {IN_CLOSE_NOWRITE , "IN_CLOSE_NOWRITE"} ,
- {IN_CREATE , "IN_CREATE"} ,
- {IN_DELETE , "IN_DELETE"} ,
- {IN_DELETE_SELF , "IN_DELETE_SELF"} ,
- {IN_MODIFY , "IN_MODIFY"} ,
- {IN_MOVE_SELF , "IN_MOVE_SELF"} ,
- {IN_MOVED_FROM , "IN_MOVED_FROM"} ,
- {IN_MOVED_TO , "IN_MOVED_TO"} ,
- {IN_OPEN , "IN_OPEN"} ,
- {IN_DONT_FOLLOW , "IN_DONT_FOLLOW"} ,
- {IN_EXCL_UNLINK , "IN_EXCL_UNLINK"} ,
- {IN_MASK_ADD , "IN_MASK_ADD"} ,
- {IN_ONESHOT , "IN_ONESHOT"} ,
- {IN_ONLYDIR , "IN_ONLYDIR"} ,
- {IN_IGNORED , "IN_IGNORED"} ,
- {IN_ISDIR , "IN_ISDIR"} ,
- {IN_Q_OVERFLOW , "IN_Q_OVERFLOW"} ,
- {IN_UNMOUNT , "IN_UNMOUNT"} ,
- };
- int monitor = inotify_init();
- if ( -1 == monitor ) {
- ERROR("monitor");
- }
- int watcher = inotify_add_watch(monitor, target, IN_ALL_EVENTS);
- if ( -1 == watcher ) {
- ERROR("inotify_add_watch");
- }
- FILE *monitor_file = fdopen(monitor, "r");
- char last_name[1024];
- char name[1024];
- /* event:inotify_event -> name:char[event.len] */
- while (true) {
- inotify_event event;
- if ( -1 == freadsome(&event, sizeof(event), monitor_file) ) {
- ERROR("freadsome");
- }
- if (event.len) {
- freadsome(name, event.len, monitor_file);
- } else {
- sprintf(name, "FD: %d\n", event.wd);
- }
- if (strcmp(name, last_name) != 0) {
- puts(name);
- strcpy(last_name, name);
- }
- /* 显示event的mask的含义 */
- for (int i=0; i<sizeof(event_masks)/sizeof(EventMask); ++i) {
- if (event.mask & event_masks[i].flag) {
- printf("\t%s\n", event_masks[i].name);
- }
- }
- }
- return 0;
- }
#include <unistd.h>
#include <sys/inotify.h>
#include <stdio.h>
#include <error.h>
#include <errno.h>
#include <string.h>
#define ERROR(text) error(1, errno, "%s", text)
struct EventMask {
int flag;
const char *name;
};
int freadsome(void *dest, size_t remain, FILE *file)
{
char *offset = (char*)dest;
while (remain) {
int n = fread(offset, 1, remain, file);
if (n==0) {
return -1;
}
remain -= n;
offset += n;
}
return 0;
}
int main(int argc, char *argv[])
{
const char *target;
if (argc == 1) {
target = ".";
} else {
target = argv[1];
}
EventMask event_masks[] = {
{IN_ACCESS , "IN_ACCESS"} ,
{IN_ATTRIB , "IN_ATTRIB"} ,
{IN_CLOSE_WRITE , "IN_CLOSE_WRITE"} ,
{IN_CLOSE_NOWRITE , "IN_CLOSE_NOWRITE"} ,
{IN_CREATE , "IN_CREATE"} ,
{IN_DELETE , "IN_DELETE"} ,
{IN_DELETE_SELF , "IN_DELETE_SELF"} ,
{IN_MODIFY , "IN_MODIFY"} ,
{IN_MOVE_SELF , "IN_MOVE_SELF"} ,
{IN_MOVED_FROM , "IN_MOVED_FROM"} ,
{IN_MOVED_TO , "IN_MOVED_TO"} ,
{IN_OPEN , "IN_OPEN"} ,
{IN_DONT_FOLLOW , "IN_DONT_FOLLOW"} ,
{IN_EXCL_UNLINK , "IN_EXCL_UNLINK"} ,
{IN_MASK_ADD , "IN_MASK_ADD"} ,
{IN_ONESHOT , "IN_ONESHOT"} ,
{IN_ONLYDIR , "IN_ONLYDIR"} ,
{IN_IGNORED , "IN_IGNORED"} ,
{IN_ISDIR , "IN_ISDIR"} ,
{IN_Q_OVERFLOW , "IN_Q_OVERFLOW"} ,
{IN_UNMOUNT , "IN_UNMOUNT"} ,
};
int monitor = inotify_init();
if ( -1 == monitor ) {
ERROR("monitor");
}
int watcher = inotify_add_watch(monitor, target, IN_ALL_EVENTS);
if ( -1 == watcher ) {
ERROR("inotify_add_watch");
}
FILE *monitor_file = fdopen(monitor, "r");
char last_name[1024];
char name[1024];
/* event:inotify_event -> name:char[event.len] */
while (true) {
inotify_event event;
if ( -1 == freadsome(&event, sizeof(event), monitor_file) ) {
ERROR("freadsome");
}
if (event.len) {
freadsome(name, event.len, monitor_file);
} else {
sprintf(name, "FD: %d\n", event.wd);
}
if (strcmp(name, last_name) != 0) {
puts(name);
strcpy(last_name, name);
}
/* 显示event的mask的含义 */
for (int i=0; i<sizeof(event_masks)/sizeof(EventMask); ++i) {
if (event.mask & event_masks[i].flag) {
printf("\t%s\n", event_masks[i].name);
}
}
}
return 0;
}
4913 IN_CREATE IN_OPEN IN_ATTRIB IN_CLOSE_WRITE IN_DELETE inotify.cc IN_MOVED_FROM inotify.cc~ IN_MOVED_TO inotify.cc IN_CREATE IN_OPEN IN_MODIFY IN_CLOSE_WRITE IN_ATTRIB inotify.cc~ IN_DELETE
创建一个4913文件用于检测vim对目录的控制权限
把inotify.cc更名为inotify.cc~
新建inotify.cc,并写入buffer
删除inotify.cc~