最近在写一个云备份的项目,其中有一个模块是要监控计算机本地的文件,于是我翻了翻linux/unix系统编程手册发现了inotify这个用于文件监控的框架
1)inotify机制可用于监控文件或目录。当监控目录时,与该目录自身以及该目录下面的文件都会被监控,其上有事件发生时都会通知给应用程序
2)inotify监控机制为非递归,若应用程序有意监控整个目录子树内的事件,则需对该树中的每个目录发起inotify_add_watch()调用
3)可使用select(),poll(),epoll()以及由信号驱动的I/O来监控inotify文件描述符
1)inotify_init()系统调用可创建一新的inotify实例
#include
int inotify_init(void);
2)针对fd所指的inotify实例的监控列表,系统调用inotify_add_watch()可以追加新的监控项
#include
int inotify_add_watch(int fd,const char *pathname,uint32_t mask);
参数mask为一位掩码,针对pathname定义了想要监控的事件,此函数的返回值为一个用于唯一指代此监控项的描述符
IN_ACCESS 文件被访问
IN_ATTRIB 文件元数据改变
IN_CLOSE_WRITE 关闭为了写入而打开的文件
IN_CREATE 在受监控目录下创建了文件或目录
IN_DELETE 在受监控目录内删除了文件或目录
IN_DELETE_SELF 删除了受监控目录/文件本身
IN_MODIFY 文件被修改
IN_MODIFY_SELF 移动受监控目录或文件本身
IN_MOVED_FROM 文件移除受监控目录
IN_MOVED_TO 将文件移到受监控目录
IN_OPEN 文件被打开
IN_ALL_EVENTS 以上所有输出事件的统称
IN_MOVE IN_MOVED_FROM | IN_MOVED_TO事件的统称
IN_ONESHOT 只监控pathname的一个事件
IN_ONLYDIR pathname不为目录时会失败
对于上述一些事件的说明:
1)当文件的元数据(比如,权限,所有权,链接计数,扩展属性,用户ID,或组ID等)改变时,会发生IN_ATTRIB事件
2)删除受监控对象时会发生IN_DELETE_SELF
3)重命名对象时会发生IN_MORE_SELF事件
4)ONE_SHOT允许只监控pathname的一个事件,事件发生后,监控项会自动从监控列表消失
将监控项项在监控列表中登记后,应运程序可用read()从inotify的文件描述符中读取事件,以判定发生了那些事件。若读取之时还没有发生任何事件,则read()会阻塞,直至有事件产生,事件发生后,每次调用read()会返回一个缓存区,内含一个或多个如下类型的结构体
struct inotify_event
{
int wd;
uint32_t mask;
uint32_t cookie;
uint32_t len;
char name[];
}
.字段wd指名发生事件的是哪个监控描述符,该字段值由之前对inotify_add_watch()的调用返回。因为用read()读到的是inotify文件中的所有事件,可是当inotify同时监控多个目录或文件时我们应该如何区分读到的内容呢,这是wd就派上了用场,我们可以用wd来做区分
.mask字段返回了描述该事件的位掩码
.cookie字段将相关事件联系到一起,目前只有对重命名时才会用到
.len字段表示实际分配给name字段的字节数
.name字段则是标示该文件
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define BUF_LEN 1000
void displayInotifyEvent(struct inotify_event *i)
{
printf(" wd = %2d; ",i->wd);
if(i->cookie > 0)
{
printf("cokkie = %4d; ",i->cookie);
}
printf("mask = ");
if(i->mask & IN_ACCESS) printf("IN_ACCESS\n");
if(i->mask & IN_DELETE_SELF) printf("IN_DELETE_SELF\n");
if(i->mask & IN_MODIFY) printf("IN_MODIFY\n");
if(i->mask & IN_OPEN) printf("IN_OPEN\n");
if(len > 0)
{
printf("name = %s\n",i->name);
}
}
int main(int argc,char **argv)
{
int inotifyFd,wd,j;
char buf[BUF_LEN];
ssize_t numRead;
char *p;
struct inotify_event *event;
int flags;
if(argc < 2 )
{
printf("error\n");
}
inotifyFd = inotify_init();
if(inotifyFd == -1)
{
printf("初始化失败");
}
wd = inotify_add_watch(inotifyFd,argv[1],IN_ALL_EVENTS);
if(wd == -1)
{
printf("error\n");
}
printf("Watching %s using wd %d\n",argv[1],wd);
while(1)
{
numRead = read(inotifyFd,buf,BUF_LEN);
if(numRead == -1)
{
printf("read error\n");
}
printf("Read %ldbytes from inotify fd\n",(long)numRead);
for(p=buf;p < buf+numRead;)
{
event = (struct inotify_event *)p;
displayInotifyEvent(event);
p+=sizeof(struct inotify_event) + event->len;
}
}
return 0;
}