用于文件系统监视的数据结构:
各个数据机构之间的关系:
1、首先是inode结构,文件系统的每个节点inode中有一个指针,指向watch链表(如下);
2、watch链表中的成员是watch,一个watch就是结构inotify_watch的一个实例(对象),inotify机制的监视就是通过watch实现的;
结构inotify_watch中包含时间掩码,watch处理实例等等。inotify_watch的结构如下:
inotify_watch中的各个参数说明:
(1)、h_list:用于挂接在inotify_handle结构的watches链表上;
(2)、i_list:用于挂接在文件节点的watch链表上;
(3)、count:引用计数;
(4)、与watch相关的inotify_handle处理实例,其中有用于连接watch(inotify_watch实例)的链表,因为一个监视处理实例(inotify_handle)可以用于多个watch;
(5):wd:watch描述字
(6):mask:watch的事件掩码,就是当当该掩码被设置是,调用inotify_handle的处理函数;
3、inotify_handle代表一个inotify机制的监视处理实例,其中包含处理监视事件的操作函数集,每个监视处理实例可用于多个watch,这些watch形成链表,由成员watches指向这个链表,因此inotify_handle中也有一个mutex互斥锁,用于保护自身的watches链表;
其结构如下:
4、至于inotify_handle中的结构inotify_operations是inotify操作函数集,用于事件处理和销毁watch,其结构定义为:
说明:
(1)、上面都是关于数据结构的定义,实际上在系统中存在的(挂接在链表上的)是这些数据结构的对象,理解的时候不要混淆;
(2)、可以看到inotify_watch数据结构和inotify_handle数据结构中都含有引用计数count,所以一个watch实例可以被多次引用;一个watch处理实例也可以被多个watch引用,且通过watch处理实例中的watches链表连接;
inotify机制的事件处理说明:当文件因操作发生改变时,文件系统的inotify机制hook函数(hook函数存在于文件系统的各个操作函数之中)会设置事件掩码,并调用事件处理函数inotify_inode_queue_event进行事件处理:
函数inotify_inode_queue_event遍历文件或目录节点上的watch链表,对事件感兴趣的watch(通过事件掩码判断,可通过下面例子说明)调用监视处理实例的事件处理函数处理事件,如果事件是处理一次(含有掩码位IN_ONESHOT),则从监视处理实例和节点上删除watch,但其不处理IN_IGNORED事件(IN_IGNORED表示文件被忽略,这种事件的处理方式还不清楚,https://www.kernel.org/pub/linux/kernel/people/rml/inotify/headers/inotify.h中介绍:它属于系统支持的核合法事件,它们根据需要被发送到任意watch)。
inotify_inode_queue_event的定义为void inotify_inode_queue_event(struct inode *inode,u32 mask,u32 cookie,const char* name,struct inode *n_inode)
关于inotify_inode_queue_event的参数说明如下:
参数inode表示产生事件的节点;
参数mask表示描述事件的事件掩码;
参数cookie是用于同步的cookie或为0;
参数name表示文件名;
参数n_inode表示与文件名name相关的节点。
函数inotify_inode_quque_event列出如下:
可以看出它是将自身的掩码和hook函数设置的掩码进行比较,如果watch中含有事件,就调用其监视处理函数(如果只处理一次,还要调用watch接口维护函数删除watch)。
关于list_for_each_entry_safe可参见:
http://www.linuxidc.com/Linux/2013-01/78002p7.htm