Linux 文件操作监控inotify功能及实现原理

2024-03-10 04:58

本文主要是介绍Linux 文件操作监控inotify功能及实现原理,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1. inotify主要功能

它是一个内核用于通知用户空间程序文件系统变化的机制。

众所周知,Linux 桌面系统与 MAC 或 Windows 相比有许多不如人意的地方,为了改善这种状况,开源社区提出用户态需要内核提供一些机制,以便用户态能够及时地得知内核或底层硬件设备发生了什么,从而能够更好地管理设备,给用户提供更好的服务,如hotplug、udev和 inotify 就是这种需求催生的。Hotplug 是一种内核向用户态应用通报关于热插拔设备一些事件发生的机制,桌面系统能够利用它对设备进行有效的管理,udev动态地维护 /dev 下的设备文件,inotify 是一种文件系统的变化通知机制,如文件增加、删除等事件可以立刻让用户态得知,该机制是著名的桌面搜索引擎项目beagle 引入的,并在Gamin 等项目中被应用。
缺点只能单独监控一个目录或文件,不能监控目录下的所有子目录,想要监控子目录必须得自己通过递归的方法将所有目录都添加到监控中去

2.用户接口

在用户态,inotify 通过三个系统调用和在返回的文件描述符上的文件I/ 操作来使用,使用inotify 的第一步是创建inotify 实例:

640?wx_fmt=png


    每一个 inotify 实例对应一个独立的排序的队列。

    文件系统的变化事件被称做 watches 的一个对象管理,每一个 watch 是一个二元组(目标,事件掩码),目标可以是文件或目录,事件掩码表示应用希望关注的inotify 事件,每一个位对应一个inotify 事件。Watch对象通过 watch描述符引用,watches 通过文件或目录的路径名来添加。目录watches 将返回在该目录下的所有文件上面发生的事件。

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


 

640?wx_fmt=png

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

    下面的函数用于删除一个 watch:

640?wx_fmt=png


    fd 是 inotify_init() 返回的文件描述符,wd 是 inotify_add_watch() 返回的 watch 描述符。Ret 是函数的返回值。

 

    文件事件用一个 inotify_event 结构表示,它通过由 inotify_init() 返回的文件描述符使用通常文件读取函数 read 来获得

640?wx_fmt=png


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

 

    通过 read 调用可以一次获得多个事件,只要提供的 buf 足够大。

640?wx_fmt=png


    buf 是一个inotify_event 结构的数组指针,BUF_LEN指定要读取的总长度,buf大小至少要不小于BUF_LEN,该调用返回的事件数取决于BUF_LEN 以及事件中文件名的长度。Len为实际读去的字节数,即获得的事件的总长度。

    可以在函数inotify_init() 返回的文件描述符fd 上使用 select()或poll(), 也可以在 fd 上使用 ioctl 命令 FIONREAD来得到当前队列的长度。close(fd)将删除所有添加到 fd 中的 watch 并做必要的清理。

640?wx_fmt=png


3. 内核实现原理

 在内核中,每一个 inotify 实例对应一个inotify_device 结构:

640?wx_fmt=png


    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 结构中增加了两个字段:

640?wx_fmt=png


    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 结构中增加了两个字段:

640?wx_fmt=png


   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 上。

 

640?wx_fmt=jpeg


这篇关于Linux 文件操作监控inotify功能及实现原理的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/793127

相关文章

流媒体平台/视频监控/安防视频汇聚EasyCVR播放暂停后视频画面黑屏是什么原因?

视频智能分析/视频监控/安防监控综合管理系统EasyCVR视频汇聚融合平台,是TSINGSEE青犀视频垂直深耕音视频流媒体技术、AI智能技术领域的杰出成果。该平台以其强大的视频处理、汇聚与融合能力,在构建全栈视频监控系统中展现出了独特的优势。视频监控管理系统EasyCVR平台内置了强大的视频解码、转码、压缩等技术,能够处理多种视频流格式,并以多种格式(RTMP、RTSP、HTTP-FLV、WebS

linux-基础知识3

打包和压缩 zip 安装zip软件包 yum -y install zip unzip 压缩打包命令: zip -q -r -d -u 压缩包文件名 目录和文件名列表 -q:不显示命令执行过程-r:递归处理,打包各级子目录和文件-u:把文件增加/替换到压缩包中-d:从压缩包中删除指定的文件 解压:unzip 压缩包名 打包文件 把压缩包从服务器下载到本地 把压缩包上传到服务器(zip

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

深入探索协同过滤:从原理到推荐模块案例

文章目录 前言一、协同过滤1. 基于用户的协同过滤(UserCF)2. 基于物品的协同过滤(ItemCF)3. 相似度计算方法 二、相似度计算方法1. 欧氏距离2. 皮尔逊相关系数3. 杰卡德相似系数4. 余弦相似度 三、推荐模块案例1.基于文章的协同过滤推荐功能2.基于用户的协同过滤推荐功能 前言     在信息过载的时代,推荐系统成为连接用户与内容的桥梁。本文聚焦于

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖

C++11第三弹:lambda表达式 | 新的类功能 | 模板的可变参数

🌈个人主页: 南桥几晴秋 🌈C++专栏: 南桥谈C++ 🌈C语言专栏: C语言学习系列 🌈Linux学习专栏: 南桥谈Linux 🌈数据结构学习专栏: 数据结构杂谈 🌈数据库学习专栏: 南桥谈MySQL 🌈Qt学习专栏: 南桥谈Qt 🌈菜鸡代码练习: 练习随想记录 🌈git学习: 南桥谈Git 🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈�

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

hdu4407(容斥原理)

题意:给一串数字1,2,......n,两个操作:1、修改第k个数字,2、查询区间[l,r]中与n互质的数之和。 解题思路:咱一看,像线段树,但是如果用线段树做,那么每个区间一定要记录所有的素因子,这样会超内存。然后我就做不来了。后来看了题解,原来是用容斥原理来做的。还记得这道题目吗?求区间[1,r]中与p互质的数的个数,如果不会的话就先去做那题吧。现在这题是求区间[l,r]中与n互质的数的和