Linux inotify功能及实现原理
http://www.cnblogs.com/jiejnan/archive/2012/05/18/2507476.html
简介: 当需要对 Linux®文件系统进行高效率、细粒度、异步地监控时,可以采用 inotify。可利用它对用户空间进行安全、性能、以及其他方面的监控。
至于inotify的基本介绍可以看下面链接
http://www.ibm.com/developerworks/cn/linux/l-inotify/index.html?ca=drs-
这里主要说下自己试验的总结:
- 何时需要自己调用inotify_rm_watch
- 合适需要自己调用inotify_add_watch
- read调用注意事项
对于1,出现moved_from而没有出现moved_to时,这就需要自 己调用inotify_rm_watch把移走的文件目录(移到非监控目录下)监控删除,这个目录下面的子目录会自动删除的 。像其它操作:删除监控目录,监控目录在大的监控目录下移进移出是不需要自己调用inotify_rm_watch的,因为系统自动处理,产生的事件分别 为delete_self和move_self。
对于2, 这要看你是否需要递归监控每个目录,如果是,那么当你在监控目录下建立一个新目录时,就需要调用inotify_add_watch;放心系统不会出现单 独的moved_to, 如果你从非监控目录下copy一个目录到监控目录下,那么inotify产生的事件是create (目录或文件),而不会是moved_to的,但可以单独产生moved_from事件,如情况1所说。
对与3,要知道下面红色的限制,
/proc interfaces
The following interfaces can be used to limit the amount of kernel memory consumed by inotify:
/proc/sys/fs/inotify/max_queued_events
The value in this
file is used when an application calls inotify_init(2) to set an upper
limit on the number of events that can be queued to the
corresponding inotify instance. Events in excess of this limit are dropped, but an N_Q_OVERFLOW event is always generated.
/proc/sys/fs/inotify/max_user_instances
This specifies an upper limit on the number of inotify instances that can be created per real user ID.
/proc/sys/fs/inotify/max_user_watches
This specifies an upper limit on the number of watches that can be created per real user ID.
如果你监控的目录很大,那么其它限制你也必须考虑,调用read时,要注意返回的是一个完整的
struct inotify_event {
int wd; /* Watch descriptor */
uint32_t mask; /* Mask of events */
uint32_t cookie; /* Unique cookie associating related
events (for rename(2)) */
uint32_t len; /* Size of name field */
char name[]; /* Optional null-terminated name */
};
结构。
http://blog.csdn.net/myarrow/article/details/7096460
1. inotify主要功能
它是一个内核用于通知用户空间程序文件系统变化的机制。
众所周知,Linux 桌面系统与 MAC 或 Windows 相比有许多不如人意的地方,为了改善这种状况,开源社区提出用户态需要内核提供一些机制,以便用户态能够及时地得知内核或底层硬件设备发生了什么,从而能 够更好地管理设备,给用户提供更好的服务,如 hotplug、udev 和 inotify 就是这种需求催生的。Hotplug 是一种内核向用户态应用通报关于热插拔设备一些事件发生的机制,桌面系统能够利用它对设备进行有效的管理,udev 动态地维护 /dev 下的设备文件,inotify 是一种文件系统的变化通知机制,如文件增加、删除等事件可以立刻让用户态得知,该机制是著名的桌面搜索引擎项目 beagle 引入的,并在 Gamin 等项目中被应用。
2. 用户接口
在用户态,inotify 通过三个系统调用和在返回的文件描述符上的文件 I/ 操作来使用,使用 inotify 的第一步是创建 inotify 实例:
int fd = inotify_init (); |
每一个 inotify 实例对应一个独立的排序的队列。
文件系统的变化事件被称做 watches 的一个对象管理,每一个 watch 是一个二元组(目标,事件掩码),目标可以是文件或目录,事件掩码表示应用希望关注的 inotify 事件,每一个位对应一个 inotify 事件。Watch 对象通过 watch描述符引用,watches 通过文件或目录的路径名来添加。目录 watches 将返回在该目录下的所有文件上面发生的事件。
下面函数用于添加一个 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 { |
结构中的 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); |
3. 内核实现原理
在内核中,每一个 inotify 实例对应一个 inotify_device 结构:
struct inotify_device { |
d_list 指向所有 inotify_device
组成的列表的,i_list 指向所有被监视 inode 组成的列表,count 是引用计数,dev 指向该 watch 所在的 inotify
实例对应的 inotify_device 结构,inode 指向该 watch 要监视的 inode,wd 是分配给该 watch
的描述符,mask 是该 watch 的事件掩码,表示它对哪些文件系统事件感兴趣。
结构 inotify_device 在用户态调用
inotify_init() 时创建,当关闭 inotify_init()返回的文件描述符时将被释放。结构 inotify_watch
在用户态调用 inotify_add_watch()时创建,在用户态调用 inotify_rm_watch() 或 close(fd)
时被释放。
无论是目录还是文件,在内核中都对应一个 inode 结构,inotify 系统在 inode 结构中增加了两个字段:
struct inotify_watch { |
d_list 指向所有 inotify_device
组成的列表的,i_list 指向所有被监视 inode 组成的列表,count 是引用计数,dev 指向该 watch 所在的 inotify
实例对应的 inotify_device 结构,inode 指向该 watch 要监视的 inode,wd 是分配给该 watch
的描述符,mask 是该 watch 的事件掩码,表示它对哪些文件系统事件感兴趣。
结构 inotify_device 在用户态调用
inotify_init() 时创建,当关闭 inotify_init()返回的文件描述符时将被释放。结构 inotify_watch
在用户态调用 inotify_add_watch()时创建,在用户态调用 inotify_rm_watch() 或 close(fd)
时被释放。
无论是目录还是文件,在内核中都对应一个 inode 结构,inotify 系统在 inode 结构中增加了两个字段:
#ifdef CONFIG_INOTIFY |
inotify_watches 是在被监视目标上的 watch
列表,每当用户调用 inotify_add_watch()时,内核就为添加的 watch 创建一个 inotify_watch
结构,并把它插入到被监视目标对应的 inode 的 inotify_watches 列表。inotify_sem 用于同步对
inotify_watches 列表的访问。当文件系统发生第一部分提到的事件之一时,相应的文件系统代码将显示调用fsnotify_*
来把相应的事件报告给 inotify 系统,其中*号就是相应的事件名,目前实现包括:
fsnotify_move,文件从一个目录移动到另一个目录fsnotify_nameremove,文件从目录中删除
fsnotify_inoderemove,自删除fsnotify_create,创建新文件fsnotify_mkdir,创建新目录
fsnotify_access,文件被读fsnotify_modify,文件被写fsnotify_open,文件被打开
fsnotify_close,文件被关闭fsnotify_xattr,文件的扩展属性被修改fsnotify_change,文件被修改或原数据被修
改有一个例外情况,就是
inotify_unmount_inodes,它会在文件系统被 umount 时调用来通知 umount 事件给 inotify 系统。
以上提到的通知函数最后都调用
inotify_inode_queue_event(inotify_unmount_inodes直接调用
inotify_dev_queue_event ),该函数首先判断对应的inode是否被监视,这通过查看 inotify_watches
列表是否为空来实现,如果发现 inode 没有被监视,什么也不做,立刻返回,反之,遍历 inotify_watches
列表,看是否当前的文件操作事件被某个 watch
监视,如果是,调用 inotify_dev_queue_event,否则,返回。函数inotify_dev_queue_event
首先判断该事件是否是上一个事件的重复,如果是就丢弃该事件并返回,否则,它判断是否 inotify 实例即 inotify_device
的事件队列是否溢出,如果溢出,产生一个溢出事件,否则产生一个当前的文件操作事件,这些事件通过kernel_event
构建,kernel_event 将创建一个 inotify_kernel_event 结构,然后把该结构插入到对应的
inotify_device
的 events 事件列表,然后唤醒等待在inotify_device 结构中的 wq
指向的等待队列。想监视文件系统事件的用户态进程在inotify 实例(即 inotify_init() 返回的文件描述符)上调用 read
时但没有事件时就挂在等待队列 wq 上。
4. 使用示例
下面是一个使用 inotify 来监视文件系统事件的例子:
#include |
转自:http://linux.chinaitlab.com/kernel/391147_4.html
Linux inotify功能及实现原理的更多相关文章
- Linux inotify功能及实现原理【转】
转自:http://blog.csdn.net/myarrow/article/details/7096460 1. inotify主要功能 它是一个内核用于通知用户空间程序文件系统变化的机制. 众所 ...
- Linux 文件操作监控inotify功能及实现原理【转】
转自:http://blog.chinaunix.net/uid-26585427-id-5012973.html 1. inotify主要功能 它是一个内核用于通知用户空间程序文件系统变化的机制. ...
- (转)linux下文件删除的原理精华讲解(考试题答案系列)
linux下文件删除的原理精华讲解(考试题答案系列) 说明:本文为老男孩linux培训某节课前考试试题及答案分享博文内容的一部分,也是独立成题的,你可以点下面地址查看全部的内容信息.http://ol ...
- Linux下的Shell工作原理
Linux下的Shell工作原理 Linux系统提供给用户的最重要的系统程序是Shell命令语言解释程序.它不属于内核部分,而是在核心之外,以用户态方式运行.其基本功能是解释并执行用户打入的各种命令, ...
- Linux下删除文件的原理
Linux下文件删除的原理 Lniux下控制文件真正被删除的计数器 Linux是link的数量来控制文件删除的.只有当一个文件不存在任何link的时候,这个文件才会被删除.一般来讲,每个文件都有两个l ...
- [转帖]linux 清空history以及记录原理
linux 清空history以及记录原理 自己的linux 里面总是一堆 乱七八槽输错的命令 用这个办法 可以清空 linux的内容. 清爽一些. 1.当前session执行的命令,放置缓存中,执行 ...
- Zookeeper的功能以及工作原理(转)
本文转自https://www.cnblogs.com/felixzh/p/5869212.html Zookeeper的功能以及工作原理 1.ZooKeeper是什么?ZooKeeper是一个分 ...
- Remmina:一个 Linux 下功能丰富的远程桌面共享工具(转载)
Remmina:一个 Linux 下功能丰富的远程桌面共享工具 作者: Aaron Kili 译者: LCTT geekpi | 2017-05-10 09:05 评论: 2 收藏: 4 Remm ...
- 【转载】使用宝塔Linux面板功能查看服务器CPU使用率
运维过阿里云服务器或者腾讯云服务器的运维人员都知道,针对耗资源以及高并发的应用,很多时候我们需要关注云服务器的资源利用率情况,如最近一段时间内CPU的使用率.内存占用率等情况信息.阿里云和腾讯云官方后 ...
随机推荐
- snmp数据包分析
今天看了一下snmp数据包的报文格式,用wireshark抓了两个数据包来分析. 先说说snmp get-request的书报包格式吧,get-next-request,get-response,se ...
- SQL Server Reporting Services – Insufficient Rights Error
http://www.sql-server-performance.com/2011/security-ssrs-reporting-error/ SQL Server Reporting Servi ...
- ibatis查找date类型
ibatis从oracle查询的时候,返回的类型是java.sql.Date,这个类型是不带时分秒的,我们只有在写sql的时候用to_char来转换.
- TF-IDF与余弦相似性的应用(三):自动摘要
有时候,很简单的数学方法,就可以完成很复杂的任务. 这个系列的前两部分就是很好的例子.仅仅依靠统计词频,就能找出关键词和相似文章.虽然它们算不上效果最好的方法,但肯定是最简便易行的方法. 今天,依然继 ...
- MVC4 网站发布(整理 + 部分转载 + 部分问题收集和解决方案)
网站发布步骤: 这部分是转载文章 在此标明出处,以前有文章是转的没标明的请谅解,因为有些已经无法找到出处,或者与其它原因. 如有冒犯请联系本人,或删除,或标明出处. 因为好的文章,以前只想收藏,但连接 ...
- SAXReader
DOM4j读取XML文件(SAXReader) 一. 总结: Document document=new SAXReader.reader(“xml文路径/文件名xxx.xml”);//得到Docum ...
- SQL SERVER数据库修改是否区分大小写
昨天去客户,发现程序无法应用,跟踪错误提示,提示的大致意思是“数据库表名和数据库字段名不存在”.查询后发现是SQL Server数据库设置了区分大小写的缘故(一般安装时,Oracle的正确安装下是默认 ...
- Nagios全方位告警接入-电话/微信/短信都支持
百度告警平台地址: http://gaojing.baidu.com 联系我们: 邮箱:gaojing@baidu.com 电话:13924600771 QQ群:183806029 Nagios接入 ...
- c++取小数整数部分
#include<math.h> double ceil(double x) //向上取整 double floor(double x) //向下取整 向上取整,取比x大的第一个整数值向下 ...
- <string>和<string.h>的区别
转自:http://blog.csdn.net/houjixin/article/details/8648969 在C++开发过程中经常会遇到两个比较容易混淆的头文件引用#include<str ...