如何使用inotify_init,inotify_add_watch,inotify_rm_watch,read编写监控程序
分类: http://blog.163.com/xychenbaihu@yeah/blog/static/132229655201011209823241/2010-12-20 10:00:29| 分类: Linux系统编程 | 标签: |字号大中小 订阅
通俗点说它是一个内核用于通知用户空间程序文件系统变化的系统,并且它是powerful yet simple的。
inotify的用户接口原型主要有以下3个:
#include <sys/inotify.h>
初始化:int inotify_init(void);
int fd = inotify_init();
添加监视对象:int inotify_add_watch(int fd, const char *path, uint32_t mask);
int wd = inotify_add_watch(fd,path,mask);
fd是inotify_init()的返回值。
const char *path是要监控的文件(目录)的路径。
uint32_t mask是:
IN_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 | 只监测目录 |
仅由read返回
IN_IGNORED | inotify_rm_watch,文件被删除或者文件系统被umount |
IN_ISDIR | 发生事件的是一个目录 |
IN_Q_OVERFLOW | Event队列溢出 |
IN_UNMOUNT | 文件系统unmount |
还有非常多的事件可以使用。使用man inotify可以查看所有可以监听的事件。
mask是上面这些事件的或。例如IN_ACCESS|IN_MODIFY。
返回值:wd表示对那个文件进行监控。
删除监视对象:int inotify_rm_watch(int fd, uint32_t wd);
参数fd是inotify_init的返回值。
wd是inotify_add_watch的返回值。
inotify_rm_watch删除对wd所指向的文件的监控。
读取监控发生的事件:
size_t len = read(fd, buf, BUF_LEN);
读取事件数据,buf应是一个指向inotify_event结构数组的指针。不过要注意的是inotify_event的name成员长度是可变的,这个问题后面再解释。
注意:其中buf是一个指向struct inotify_event数组的指针。
由于struct inotify_event长度是可变的,因此在读取inotify_event数组内容的时候需要动态计算一下时间数据的偏移量。index += sizeof(struct inotify_event)+event->len,len即name成员的长度。
其实还是没有讲的很清楚,不过看了下面的例子,一定非常清楚:
#include <stdio.h>
#include <unistd.h>
#include <sys/select.h>
#include <errno.h>
#include <sys/inotify.h>
static void _inotify_event_handler(struct inotify_event *event) //从buf中取出一个事件。
{
printf("event->mask: 0x%08x\n", event->mask);
printf("event->name: %s\n", event->name);
}
int main(int argc, char **argv)
{
if (argc != 2) {
printf("Usage: %s <file/dir>\n", argv[0]);
return -1;
}
unsigned char buf[1024] = {0};
struct inotify_event *event = NULL;
int fd = inotify_init(); //初始化
int wd = inotify_add_watch(fd, argv[1], IN_ALL_EVENTS); //监控指定文件的ALL_EVENTS。
for (;;)
{
fd_set fds;
FD_ZERO(&fds);
FD_SET(fd, &fds);
if (select(fd + 1, &fds, NULL, NULL, NULL) > 0) //监控fd的事件。当有事件发生时,返回值>0
{
int len, index = 0;
while (((len = read(fd, &buf, sizeof(buf))) < 0) && (errno == EINTR)); //没有读取到事件。
while (index < len)
{
event = (struct inotify_event *)(buf + index);
_inotify_event_handler(event); //获取事件。
index += sizeof(struct inotify_event) + event->len; //移动index指向下一个事件。
}
}
}
inotify_rm_watch(fd, wd); //删除对指定文件的监控。
return 0;
}