NAME
INOTIFY 监测文件系统事件
DESCRIPTION
inotify API提供机制来监测文件系统事件。可以用来监测单独的文件或目录。当目录被监测时,inotify会返回目录自己的事件以及目录中文件的事件。
下列系统调用可以被使用:inotify_init, inotify_add_watch, inotify_rm_watch, read, close.
inotify_init 创建一个inotify实例并返回一个与该实例相关连的file descriptor。
inotify_add_watch 操作与inotify实例相关联的"watch list", watch list中的每一项"watch" 中指定了文件或目录的路径。kernel会监视与该路径相关文件有关的一些事件。inotify_add_watch创建一个新的watch item或修改一个已经存在的watch。 每一个watch都有一个独一无二的"watch descriptor", 一个在inotify_add_watch创建watch时返回的integer。
inotify_rm_watch 从watch list中删除一项。
当所有与inotify instance相关的file descriptors都被关闭后,其下所有相关的资源会被kernel释放并重用,所有相关的watches会自动被Free。
可以使用read操作inotify file descriptor来确定事件是否发生,如果事件没有发生,那么认为这个file descriptor是blocking的。read会block直到至少一个事件发生。
每次成功的read都会返回一个包含一个或多个以下结构的buffer:
struct inotify event{
int wd; /* Watch descriptor */
uint32_t mask; /* 事件掩码 */
uint32_t cookie; /* 与事件相关的独一无二的cookie */
uint32_t len; /* name的长度 */
char name[]; /* 可选的Null结尾的名字 */
};
wd 指定了哪一个发生了事件,他是之前通过inotify_add_watch返回的watch descriiptors 之一
mask 有bits构成的事件内容
cookies 与相关事件相联系的独一无二的integer。当前仅用在rename事件中, 使IN_MOVE_FROM 与 IN_MOVE_TO 这一对事件产生的结果与应用程序相关联。
name 当一个被watch的目录中的文件触发事件后,name中包含了该文件相对于被watch目录的路径,该路径以Null结尾,并且该NULL之后读出多余的字节都以NULL填充。
len 是name中的字节数 包含NULL字节;每个inotify_event结构的长度都是sizeof(inotify_event)+len。
提供给read的buffer过小所产生的行为由于kernel的版本不同而不同: 在2.6.21以前的版本,read返回0; 2.6.21版本之后read失败 发生错误EINVAL
inotify 事件
inotify_add_watch中的mask参数与read返回的inotify_event结构中的mask字段中均包含的是inotifyevent的bit mask。下面的bits 用于在调用inotify_add_watch与read的mask中表示相关的事件。
IN_ACCESS 文件被使用(读) *
IN_ATTRIB metadata被改变(权限,时间戳,扩展属性等等) *
IN_CLOSE_WRITE 以写权限打开的文件被关闭 *
IN_CLOSE_NOWRITE以非写权限打开的文件被关闭 *
IN_CREATE 文件/目录在watched的目录中被创建 *
IN_DELETE 文件/目录在watched的目录中被删除 *
IN_DELETE_SELF watched的文件/目录被删除
IN_MODIFY 文件被修改 *
IN_MOVE_SELF watched的文件/目录移动了
IN_MOVE_FROM 文件移出了watched的目录 *
IN_MOVE_TO 文件移入了watched的目录 *
IN_OPEN 文件被打开 *
当监测一个目录时,上面标注(*)的事件可以发生在目录下的文件中,这时返回的inotify_event结构中的name字段就指定了该目录下的文件名。
IN_ALL_EVENT宏包含了上述所有的事件。该宏可用于inotify_add_watch函数的mask参数中.
两个方便的宏:IN_MOVE 相当于 IN_MOVED_FROM|IN_MOVED_TO,IN_CLOSE 相当于 IN_CLOSE_WRITE|IN_CLOSE_NOEWRITE
下面一些额外的bit可以在inotify_add_watch中的mask参数中加入:
IN_DONT_FOLLOW 如果是symbolic link并不解析其中的路径
IN_MASK_ADD 如果watch已存在则在watch的mask中添加事件(代替了replace mask)
IN_ONESHOT 对该路径仅检测一个事件,触发后将其从watch list中删除
IN_ONLYDIR 仅在路径为目录时方加入watch
下面一些额外的bit可以在read中的mask参数中加入:
IN_IGNORED watch被指定删除(inotify_rm_watch)或自动删除(文件被删除或文件系统被unmounted)
IN_ISDIR 该事件的目标是目录
IN_Q_OVERFLOW 事件队列溢出(该事件的wd = -1)
IN_UNMOUNT 包含watch目标的文件系统被unmount
/proc 接口
下列的接口可以用来限制inotify消耗kernel memory的大小
/proc/sys/fs/inotify/max_queued_evnets
该文件中的值为调用inotify_init时分配给inotify instance中可排队的event的数目的最大值,超出这个值得事件被丢弃,但会触发IN_Q_OVERFLOW事件。
/proc/sys/fs/inotify/max_user_instances
其中指定了每一个real user ID可创建的inotify instatnces的数量上限
/proc/sys/fs/inotify/max_user_watches
指定了每个inotify instance相关联的watches的上限
注意
Inotify file descriptors 可以使用select, poll, epoll来监视
如果在inotify file descriptor上连续发生的inotify事件是相同的(相同的wd, mask, cookie,name),那么他们会被合并到一个事件中
通过读inotify file descriptor返回的事件是排序的队列。
FIONREAD ioctl 返回从inotify file descriptor中可读的字节数
Inotify 监测目录并不是递归的:为了监视watch目录下的子目录 必须增加一个watch
BUGs
2.6.16前的内核版本中, IN_ONESHOT mask标志不工作