加入收藏 | 设为首页 | 会员中心 | 我要投稿 帝国网站管理系统 (https://www.0356zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 服务器 > 安全 > 正文

监听风云 | Inotify 达成原理

发布时间:2021-06-09 09:36:57 所属栏目:安全 来源:互联网
导读:重要的数据结构 鲁迅先生说过:程序 = 数据结构 + 算法 想想如果让我们来设计 inotify 应该如何实现呢?下面来分析一下: 我们知道,inotify 是用来监控文件或目录的变动事件,所以应该定义一个对象来存储被监听的文件或目录列表和它们所发生的事件列表(在内
重要的数据结构
鲁迅先生说过:程序 = 数据结构 + 算法
想想如果让我们来设计 inotify 应该如何实现呢?下面来分析一下:
我们知道,inotify 是用来监控文件或目录的变动事件,所以应该定义一个对象来存储被监听的文件或目录列表和它们所发生的事件列表(在内核中定义了 inotify_device 对象来存储被监听的文件列表和事件列表)。
另外,当对被监听的文件或目录进行读写操作时会触发相应的事件产生。所以,应该在读写操作相关的系统调用中嵌入产生事件的动作(在内核中由 inotify_dev_queue_event 函数产生事件)。
在介绍 inotify 的实现前,我们先来了解下其原理。inotify 的原理如下:
当用户调用 read 或者 write 等系统调用对文件进行读写操作时,内核会把事件保存到 inotify_device 对象的事件队列中,然后唤醒等待 inotify 事件的进程。正所谓一图胜千言,所以我们通过下图来描述此过程:
 
从上图可知,当应用程序调用 read 函数读取文件的内容时,最终会调用 inotify_dev_queue_event 函数来触发事件,调用栈如下:
read() 
└→ sys_read() 
   └→ vfs_read() 
      └→ fsnotify_access() 
         └→ inotify_inode_queue_event() 
            └→ inotify_dev_queue_event() 
inotify_dev_queue_event 函数主要完成两个工作:
创建一个表示事件的 inotify_kernel_event 对象,并且把其插入到 inotify_device 对象的 events 列表中。
唤醒正在等待 inotify 发生事件的进程,等待的进程放置在 inotify_device 对象的 wq 字段中。
上面主要涉及到两个对象,inotify_device 和 inotify_kernel_event,我们先来介绍一下这两个对象的作用。
inotify_device:内核使用此对象来描述一个 inotify,是 inotify 的核心对象。
intoify_kernel_event:内核使用此对象来描述一个事件。
我们来看看这两个对象的定义。
1. inotify_device对象
内核使用 inotify_device 来管理 inotify 监听的对象和发生的事件,其定义如下:
1struct inotify_device { 
2    wait_queue_head_t       wq; 
3    ... 
4    struct list_head        events; 
5    ... 
6    struct inotify_handle   *ih; 
7    unsigned int            event_count; 
8    unsigned int            max_events; 
9}; 
下面我们介绍一下各个字段的作用:
wq:正在等待当前 inotify 发生事件的进程列表。
events:保存由 inotify 监听的文件或目录所发生的事件。
ih:内核用来存储 inotify 监听的文件或目录,下面会介绍。
event_count:inotify 监听的文件或目录所发生的事件数量。
max_events:inotify 能够保存最大的事件数量。
下图描述了 inotify_device 对象中两个比较重要的队列(等待队列 和 事件队列):
 
当事件队列中有数据时,就可以通过调用 read 函数来读取这些事件。
2. inotify_kernel_event对象
内核使用 inotify_kernel_event 对象来存储一个事件,其定义如下:
struct inotify_kernel_event { 
   struct inotify_event    event; 
    struct list_head        list; 
    char                    *name; 
}; 
可以看出,inotify_kernel_event 对象只是对 inotify_event 对象进行扩展而已,而我们在《监听风云 - inotify介绍》一文中已经介绍过 inotify_event 对象。
inotify_kernel_event 对象在 inotify_event 对象的基础上增加了 list 字段和 name 字段:
list:用于把所有由 inotify 监听的文件或目录所发生的事件连接起来,
name:用于记录发生事件的文件名或目录名。

(编辑:帝国网站管理系统)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读