1. 简介:
Inotify 是一个 Linux 内核特性,它监控文件系统,并且及时向专门的应用程序发出相关的事件警告,比如删除、读、写和卸载操作等。您还可以跟踪活动的源头和目标等细节。
使用 inotify 很简单:创建一个文件描述符,附加一个或多个监视器(一个监视器 是一个路径和一组事件),然后使用 read()
方法从描述符获取事件信息。read()
并不会用光整个周期,它在事件发生之前是被阻塞的。
更好的是,因为 inotify 通过传统的文件描述符工作,您可以利用传统的 select()
系统调用来被动地监控监视器和许多其他输入源。两种方法 — 阻塞文件描述符和使用 select()
— 都避免了繁忙轮询。
要使用 inotify,您必须具备一台带有 2.6.13 或更新内核的 Linux 机器(以前的 Linux 内核版本使用更低级的文件监控器 dnotify)。如果您不知道内核的版本,请转到 shell,输入 uname -a
2. 首先看一下inotify.h中定义的watch mask:
IN_ACCESS
The file was read from.
IN_MODIFY
The file was written to.
IN_ATTRIB
The file’s metadata (for example, the owner, permissions, or extended attributes) was changed.
IN_CLOSE_WRITE
The file was closed and had been open for writing.
IN_CLOSE_NOWRITE
The file was closed and had not been open for writing.
IN_OPEN
The file was opened.
IN_MOVED_FROM
A file was moved away from the watched directory.
IN_MOVED_TO
A file was moved into the watched directory.
IN_CREATE
A file was created in the watched directory.
IN_DELETE
A file was deleted from the watched directory.
IN_DELETE_SELF
The watched object itself was deleted.
IN_MOVE_SELF
The watched object itself was moved.
The following events are also defined, grouping two or more events into a single value:
IN_ALL_EVENTS
All legal events.
IN_CLOSE
All events related to closing (currently, both IN_CLOSE_WRITE and IN_CLOSE_NOWRITE).
IN_MOVE
All move-related events (currently, both IN_MOVED_FROM and IN_MOVED_TO).
有了以上的watch mask就可以从终端的输出清晰的得知文件进行了什么样的操作。
2. 上代码:
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <sys/inotify.h>
- #include <unistd.h>
-
- #define EVENT_NUM 12
-
- char *event_str[EVENT_NUM] =
- {
- "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"
- };
-
- int main(int argc, char *argv[])
- {
- int fd;
- int wd;
- int len;
- int nread;
- char buf[BUFSIZ];
- struct inotify_event *event;
- int i;
-
- if (argc < 2)
- {
- fprintf(stderr, "%s path\n", argv[0]);
- return -1;
- }
-
- fd = inotify_init();
- if (fd < 0)
- {
- fprintf(stderr, "inotify_init failed\n");
- return -1;
- }
-
- wd = inotify_add_watch(fd, argv[1], IN_ALL_EVENTS);
- if (wd < 0)
- {
- fprintf(stderr, "inotify_add_watch %s failed\n", argv[1]);
- return -1;
- }
-
- buf[sizeof(buf) - 1] = 0;
- while ((len = read(fd, buf, sizeof(buf) - 1)) > 0)
- {
- nread = 0;
- while (len > 0)
- {
- event = (struct inotify_event *)&buf[nread];
- for (i = 0; i<EVENT_NUM; i++)
- {
- if ((event->mask >> i) & 1)
- {
- if (event->len > 0)
- fprintf(stdout, "%s --- %s\n", event->name, event_str[i]);
- else
- fprintf(stdout, "%s --- %s\n", " ", event_str[i]);
- }
- }
- nread = nread + sizeof(struct inotify_event) + event->len;
- len = len - sizeof(struct inotify_event) - event->len;
- }
- }
-
- return 0;
- }
然后新建inotify.c文件,将代码粘贴进去中,终端使用如下命令编译测试:
gcc inotify.c -o ity
终端运行可执行文件ity:
$./ity //path to watch
然后可以复制该路径下Untitled Document文件到该路径Untitled Document(copy),可以看到终端输出如下,然后就可以对照watch mask查看下输出的意思了: