inotify机制是Linux内核2.6.13以后支持的一个新的特性,功能是监视文件系统的变化。当监视到文件系统发生任何变化以后,相应的应用程序可以得到通知。inotify可以监视单个文件或甚至是某个目录的变化。
要启用inotify机制对文件或目录进行监控,一般需要顺序调用以下几个API:
1)inotify_init
最开始要创建一个inotify实例,这是通过调用inotify_init函数来实现的,其定义如下:
int inotify_init(void);
函数的返回值是一个int型的文件句柄,指向创建的inotify实例。
2)inotify_add_watch
接下来要在刚创建的inotify实例中添加上一个监视点,这需要调用inotify_add_watch函数,其定义如下:
int inotify_add_watch(int fd, const char* path, uint32_t event);
该函数共有三个参数,第一个参数就是第一步中调用inotify_init函数返回的inotify实例句柄;第二个参数是要监视的文件或目录的路径;最后一个参数是要监视的事件,每一种监视事件用一个比特位来表示,对应比特位是1的话表示要监视这个事件,0的话表示不监视,具体事件的定义如下表:
函数的返回值是一个int型的监视点描述符。
如果在inotify实例中已经存在了一个路径名相同的监视点,那么inotify_add_watch函数并不会创建一个新的监视点,而是更新那个已有的监视点。
3)read
为了确定有哪些文件系统事件发生了,需要调用read函数,如果什么事件都没有发生,则read函数会被阻塞,直到有任何监视事件发生了才会被唤醒继续执行。
ssize_t read(int fd, void *buf, size_t count);
调用的时候,第一个参数就是在第一步中inotify_init函数返回的inotify实例句柄;第二个参数是要存放读取结果的缓冲区;第三个是这个缓冲区的大小。成功返回读取的字节数,出错返回-1并设置errno。
read函数会在缓冲区中返回一个或多个inotify_event结构体,其定义如下:
struct inotify_event { __s32 wd; __u32 mask; __u32 cookie; __u32 len; char name[0]; };
wd是第二步中inotify_add_watch函数返回的监视点描述符,通过它就可以知道到底哪个被监控的目录或文件发生了变化;mask为事件掩码,通过它就可以知道,到底是哪种事件发生了;cookie是用来连接两个事件的,比如如果将一个文件从一个目录移动到另一个目录,则原来的目录会收到IN_MOVED_FROM事件,而新目录会收到IN_MOVED_TO事件,这两个事件的cookie值被设置成一样,这样就可以将这两个看似独立,但相关联的事件连接起来;len用来指定后面存放路径名name的长度;最后的name存放的是具体的路径名,但并不是用来存放被监控的那个目录或文件的路径的,它只对监控的是一个目录有效(如果监控的是一个具体的文件则无效),当那个被监控的目录中有变化时,这个name域指出到底是这个目录中的哪个文件发生了变化,并且它存放的是并不是绝对路径名,而是相对于被监控目录的路径名。
所以,这个inotify_event结构体是不定长的,其长度是:
sizeof(struct inotify_event) + len
4)inotify_rm_watch
inotify_rm_watch函数用于移除监视点,即取消对某个目录或文件的监视:
int inotify_rm_watch(int fd, int wd);
其中fd是inotify实例句柄描述符,由第一步的inotify_init函数返回;wd是监视点描述符,由第二步的inotify_add_watch函数返回。
5)close
如果inotify实例中的所有监视点都被删除掉了,并且以后也不会再添加了,则应该调用close函数,将这个inotify实例也关掉:
int close(int fd);
函数唯一的参数就是在第一步中函数返回的inotify实例句柄描述符。函数调用成功返回0,出错返回-1,并设置errno。