,动态监控之一转载此文请联系linux内核那些事儿公众号。不知道你有没有用过Dropbox。这是国外一款非常好用的云盘。您只需要在Dropbox中设置要同步的目录即可。每当此目录中的文件发生变化时,Dropbox会自动同步文件。到云端。那么,Dorpbox如何知道目录中的文件发生了变化呢?答案是通过inotfiy的系统函数实现的。我们主要分两篇文章介绍inotify的功能:本文先介绍inotify的使用,下一篇主要介绍inotify的实现原理。inotify接口其实inotify的接口比较少,只有三个:inotify_init、inotify_add_watch和inotify_rm_watch。下面分别介绍一下这三个接口的功能和原型。1、inotify_initinotify_init函数用于创建一个inotify句柄,可以认为是inotify对象。其原型如下:intinotify_init(void);2、通过inotify_add_watch创建inotify句柄后,可以调用inotify_add_watch函数添加需要监控的文件或目录。其原型如下:intinotify_add_watch(intfd,constchar*path,uint32_tmask);inotify_add_watch调用成功后,会返回被监控文件或目录的描述符。下面介绍一下各个参数的含义:fd:是inotify_init函数创建的inotify句柄。path:要监听的文件或目录的路径。mask:要监听的事件,其事件类型如下:类型描述IN_ACCESS文件被访问IN_ATTRIB文件元数据改变IN_CLOSE_WRITE关闭一个为写入而打开的文件IN_CLOSE_NOWRITE关闭一个只读文件IN_CREATE在监听目录中创建一个文件/目录IN_DELETE删除侦听目录中的文件/目录IN_DELETE_SELF侦听要删除的目录/文件本身。IN_MODIFY文件被修改IN_MOVE_SELF被监控的目录/文件本身被移动IN_MOVED文件被移动IN_OPEN文件被打开IN_ALL_EVENTS以上所有输出事件的总称3.inotify_rm_watchinotify_rm_watch函数用于删除被监控的文件或目录,原型如下:intinotify_rm_watch(intfd,uint32_twd);下面介绍各个参数的含义:fd:调用inotify_init函数返回的inotify句柄。wd:inotify_add_watch函数返回的被监视文件或目录的描述符。看完了change事件,介绍了inotify的接口,现在用一个简单的例子来说明如何使用inotify。在写inotify的例子之前,先介绍一下如何获取被监控的文件或目录的变化事件。inotify并没有提供具体的接口获取被监控文件或目录的变化事件,而是通过通用的read函数读取。我们先看一下read函数的原型:intread(intfd,void*events,size_tlen);下面说说各个参数的含义:fd:inotify_init创建的inotify句柄。events:存储变化事件的缓冲区。len:缓冲区的大小。events参数用于存储被监控文件或目录的变化事件,一般指定为inotify_event结构体数组,inotify_event结构体定义如下:structinotify_event{intwd;//被监控文件或目录的描述符(byinotify_add_watch)uint32_tmask;//Changedeventuint32_tcookie;//很少用到,可以忽略uint32_tlen;//name的长度charname[];//用来存放改变的文件或目录名};使用实例现在我们可以使用inotify来写实例了,这个实例主要介绍如何使用inotify来监控一个文件或目录,并打印它的变化事件。实际代码如下:#include#include#include#include//导入inotify的头文件/**用于打印开发的事件*/voiddisplay_event(constchar*base,structinotify_event*event){char*operate;intmask=event->mask;if(mask&IN_ACCESS)operate="ACCESS";if(mask&IN_ATTRIB)operate="ATTRIB";if(mask&IN_CLOSE_WRITE)operate="CLOSE_WRITE";if(mask&IN_CLOSE_NOWRITE)operate="CLOSE_NOWRITE";if(mask&IN_CREATE)operate="CREATE";if(mask&IN_DELETE_SELF)operate="DELETE_SELF";if(mask&IN_MODIFY)operate="MODIFY";if(mask&IN_MOVE_SELF)operate="MOVE_SELF";if(mask&IN_MOVED_FROM)operate="MOVED_FROM";if(mask&IN_MOVED_TO)operate="MOVED_TO";if(mask&IN_OPEN)operate="OPEN";if(mask&IN_IGNORED)operate="IGNORED";if(mask&IN_DELETE)operate="DELETE";if(mask&IN_UNMOUNT)operate="UNMOUNT";printf("%s/%s:%s\n",base,event->name,operate);}#defineEVENTS_BUF_SIZE4096intmain(intargc,charconst*argv[]){intfd;intnbytes,offset;chaevents[EVENTS_BUF_SIZE];structinotify_event*event;fd=inotify_init();//创建一个inotify句柄if(fd<0){printf("Failedtoinitalizeinotify\n");return-1;}//从命令行获取要监控的文件parameterorDirectorypath//添加需要监控的文件或目录,监听所有事件if(inotify_add_watch(fd,argv[1],IN_ALL_EVENTS)==-1){printf("Failedtoaddfileordirectorywatch\n");return-1;}for(;;){memset(events,0,sizeof(events));//读取事件nbytes=read(fd,events,sizeof(events));if(nbytes<=0){printf("Failedtoreadevents\n");continue;}//开始打印发生的事件for(offset=0;offsetlen;//获取下一次变化事件的偏移量}}return0;}上面的例子逻辑是比较简单,主要步骤如下:调用inotify_init函数创建inotify句柄从命令行获取需要监控的文件或目录路径,通过inotify_add_watch函数添加到inotify中进行监控。无限循环,通过read函数读取被监控文件或目录的变化事件,调用display_event函数打印事件。上面的例子比较难理解的是从events参数中获取change事件的指针。我们可以通过下图来理清获取变化事件指针的逻辑:通过上图,更容易理解如何从事件缓冲区中获取变化事件指针。更改事件指针。最后来看看我们写的例子的效果动画:总结本文主要介绍inotify的使用。在下一篇文章中,我们将介绍inotify的原理和实现,敬请期待(当然,如果你对inotify的实现不感兴趣,就别期待了。。。)。