详解Linux 2.6内核新文件系统变化机制( 二 )


下面函数用于添加一个 watch:

int wd = inotify_add_watch (fd, path, mask);

fd 是 inotify_init() 返回的文件描述符,path 是被监视的目标的路径名(即文件名或目录名),mask 是事件掩码, 在头文件 linux/inotify.h 中定义了每一位代表的事件 。可以使用同样的方式来修改事件掩码,即改变希望被通知的inotify 事件 。Wd 是 watch 描述符 。
下面的函数用于删除一个 watch:

int ret = inotify_rm_watch (fd, wd);

fd 是 inotify_init() 返回的文件描述符,wd 是 inotify_add_watch() 返回的 watch 描述符 。Ret 是函数的返回值 。
文件事件用一个 inotify_event 结构表示,它通过由 inotify_init() 返回的文件描述符使用通常文件读取函数 read 来获得:

struct inotify_event {
__s32wd;;;/* watch descriptor */
__u32mask;/* watch mask */
__u32cookie; /* cookie to synchronize two events */
__u32len;;/* length (including nulls) of name */
char;name[0] /* stub for possible name */
};

结构中的 wd 为被监视目标的 watch 描述符,mask 为事件掩码,len 为 name字符串的长度,name 为被监视目标的路径名,该结构的 name 字段为一个桩,它只是为了用户方面引用文件名,文件名是变长的,它实际紧跟在该结构的后面,文件名将被 0 填充以使下一个事件结构能够 4 字节对齐 。注意,len 也把填充字节数统计在内 。
通过 read 调用可以一次获得多个事件,只要提供的 buf 足够大 。

size_t len = read (fd, buf, BUF_LEN);

buf 是一个 inotify_event 结构的数组指针,BUF_LEN 指定要读取的总长度,buf 大小至少要不小于 BUF_LEN,该调用返回的事件数取决于 BUF_LEN 以及事件中文件名的长度 。Len 为实际读去的字节数,即获得的事件的总长度 。
可以在函数 inotify_init() 返回的文件描述符 fd 上使用 select() 或poll(), 也可以在 fd 上使用 ioctl 命令 FIONREAD 来得到当前队列的长度 。close(fd)将删除所有添加到 fd 中的 watch 并做必要的清理 。

int inotify_init (void);
int inotify_add_watch (int fd, const char *path, __u32 mask);
int inotify_rm_watch (int fd, __u32 mask);

三、内核实现机理
在内核中,每一个 inotify 实例对应一个 inotify_device 结构:

struct inotify_device {
wait_queue_head_t;;;;wq;;;/* wait queue for i/o */
struct idr;;;idr;;/* idr mapping wd -> watch */
struct semaphore;;;;;sem;;/* protects this bad boy */
struct list_head;;;;;events; /* list of queued events */
struct list_head;;;;;watches /* list of watches */
atomic_t;;;;;count/* reference count */
struct user_struct;;;*user/* user who opened this dev */
unsigned int;queue_size;;;/* size of the queue (bytes) */
unsigned int;event_count;;/* number of pending events */
unsigned int;max_events;;;/* maximum number of events */
u32;;last_wd /* the last wd allocated */
};

wq 是等待队列,被 read 调用阻塞的进程将挂在该等待队列上,idr 用于把 watch 描述符映射到对应的 inotify_watch,sem 用于同步对该结构的访问,events 为该 inotify 实例上发生的事件的列表,被该 inotify 实例监视的所有事件在发生后都将插入到这个列表,watches 是给 inotify 实例监视的 watch 列表,inotify_add_watch 将把新添加的 watch 插入到该列表,count 是引用计数,user 用于描述创建该 inotify 实例的用户,queue_size 表示该 inotify 实例的事件队列的字节数,event_count 是 events 列表的事件数,max_events 为最大允许的事件数,last_wd 是上次分配的 watch 描述符 。
每一个 watch 对应一个 inotify_watch 结构:

struct inotify_watch {
struct list_head;;;;;d_list; /* entry in inotify_device"s list */
struct list_head;;;;;i_list; /* entry in inode"s list */

推荐阅读