返回顶部
首页 > 资讯 > 操作系统 >Linux中 inotify功能的实现原理是什么
  • 447
分享到

Linux中 inotify功能的实现原理是什么

2023-06-16 12:06:15 447人浏览 薄情痞子
摘要

今天就跟大家聊聊有关linux中 inotify功能的实现原理是什么,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。1. inotify主要功能它是一个内核用于通知用户空间程序文件系统

今天就跟大家聊聊有关linux中 inotify功能的实现原理是什么,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。

1. inotify主要功能

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

众所周知,Linux 桌面系统与 Macwindows  相比有许多不如人意的地方,为了改善这种状况,开源社区提出用户态需要内核提供一些机制,以便用户态能够及时地得知内核或底层硬件设备发生了什么,从而能够更好地管理设备,给用户提供更好的服务,如  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 {         __s32           wd;                      __u32           mask;                    __u32           cookie;                  __u32           len;                     char            name[0];         };

结构中的 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);

3. 内核实现原理

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

struct inotify_device {  wait_queue_head_t wq;   struct idr idr;   struct semaphore sem;   struct list_head events;   struct list_head watches;   atomic_t count;   struct user_struct *user;   unsigned int queue_size;   unsigned int event_count;   unsigned int max_events;   u32 last_wd;   };

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 {  struct list_head d_list;   struct list_head i_list;   atomic_t count;   struct inotify_device *dev;   struct inode *inode;   s32 wd;   u32 mask;   };

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      struct list_head inotify_watches;       struct semaphore inotify_sem;   #endif

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  #include  #include   _syscall0(int, inotify_init) _syscall3(int, inotify_add_watch, int, fd, const char *, path, __u32, mask) _syscall2(int, inotify_rm_watch, int, fd, __u32, mask)  char * monitored_files[] = {     "./tmp_file",     "./tmp_dir",     "/mnt/sda3/windows_file" };  struct wd_name {     int wd;     char * name; };  #define WD_NUM 3 struct wd_name wd_array[WD_NUM];  char * event_array[] = {     "File was accessed",     "File was modified",     "File attributes were changed",     "writtable file closed",     "Unwrittable file closed",     "File was opened",     "File was moved from X",     "File was moved to Y",     "Subfile was created",     "Subfile was deleted",     "Self was deleted",     "Self was moved",     "",     "Backing fs was unmounted",     "Event queued overflowed",     "File was ignored" }; #define EVENT_NUM 16 #define MAX_BUF_SIZE 1024      int main(void) {     int fd;     int wd;     char buffer[1024];     char * offset = NULL;     struct inotify_event * event;     int len, tmp_len;     char strbuf[16];     int i = 0;          fd = inotify_init();     if (fd < 0) {         printf("Fail to initialize inotify.\n");         exit(-1);     }      for (i=0; i<WD_NUM; wd="inotify_add_watch(fd," add (event- if { len) < buffer) - *)event (((char while *)buffer; inotify_event event len); len='%d.\n",' happens, printf(?Some offset="buffer;" MAX_BUF_SIZE)) buffer, while(len="read(fd," } wd_array[i].wd="wd;" exit(-1); wd_array[i].name); %s.\n?, for watch printf(?Can?t 0) (wd IN_ALL_EVENTS); wd_array[i].name, wd_array[i].name="monitored_files[i];" i++)>mask & IN_ISDIR) {                 memcpy(strbuf, "Direcotory", 11);             }             else {                 memcpy(strbuf, "File", 5);             }             printf("Object type: %s\n", strbuf);             for (i=0; iwd != wd_array[i].wd) continue;                 printf("Object name: %s\n", wd_array[i].name);                 break;             }             printf("Event mask: %08X\n", event->mask);             for (i=0; imask & (1<len;             event = (struct inotify_event *)(offset + tmp_len);              offset += tmp_len;         }     } }

看完上述内容,你们对Linux中 inotify功能的实现原理是什么有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注编程网操作系统频道,感谢大家的支持。

--结束END--

本文标题: Linux中 inotify功能的实现原理是什么

本文链接: https://lsjlt.com/news/283645.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Linux中 inotify功能的实现原理是什么
    今天就跟大家聊聊有关Linux中 inotify功能的实现原理是什么,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。1. inotify主要功能它是一个内核用于通知用户空间程序文件系统...
    99+
    2023-06-16
  • linux中fork的实现原理是什么
    在Linux中,fork是创建新进程的系统调用之一。当调用fork系统调用时,操作系统会复制当前进程的所有资源(包括代码、数据、堆栈...
    99+
    2023-09-11
    linux
  • Linux中spin_lock的实现原理是什么
    spin_lock是Linux中的一种锁机制,用于保护共享资源,避免多个线程同时访问共享资源导致的数据不一致性问题。spin_loc...
    99+
    2023-08-08
    Linux spin_lock
  • Linux的实现原理是什么
    本篇内容主要讲解“Linux的实现原理是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Linux的实现原理是什么”吧!1 引言90年代以来,数控技术发展的一个重要趋势是数控系统的开放化。目前...
    99+
    2023-06-16
  • haproxy实现功能以及keepalived的使用原理是什么
    这篇文章将为大家详细讲解有关haproxy实现功能以及keepalived的使用原理是什么,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。haproxy能够实现的功能4层负载均衡,透明代理,7...
    99+
    2023-06-05
  • linux定时器实现的原理是什么
    Linux定时器的实现原理如下:1. 内核中的定时器是通过“定时器”数据结构来表示的。该数据结构包含了定时器的到期时间、回调函数、回...
    99+
    2023-10-09
    linux
  • Linux互斥锁的实现原理是什么
    本篇内容主要讲解“Linux互斥锁的实现原理是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Linux互斥锁的实现原理是什么”吧!互斥锁(Mutex)是在原子操作API的基础上实现的信号量行...
    99+
    2023-06-28
  • linux内核锁的实现原理是什么
    Linux内核锁的实现原理是通过硬件的原子操作指令或者特殊的指令序列来保证对共享资源的原子操作,从而实现线程之间的同步和互斥。Lin...
    99+
    2023-10-21
    linux
  • linux中pwd的功能是什么
    本文小编为大家详细介绍“linux中pwd的功能是什么”,内容详细,步骤清晰,细节处理妥当,希望这篇“linux中pwd的功能是什么”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。...
    99+
    2023-02-23
    linux pwd
  • Linux 通过Rsync+Inotify实现本、异地远程数据实时同步功能
    0x0 测试环境 总部生产服务器与分部备份服务器要求实现异地数据备份,环境如下 **centos 6.5** 生产服务器目录: /home/zytest/files 备份服务器目录: /home/zytest/fi...
    99+
    2022-06-03
    rsync+inotify实现远程实时同步 linux 远程数据同步
  • Linux利用inotify和rsync服务实现数据实时同步的原理解析
    目录文件定时同步的实现:文件实时同步的实现:inotifyinotify-tools包主要工具:inotifywait 命令:rsync工具rsync有三种工作方式:两种方式实现rsync服务器方式一:通过rsync守护...
    99+
    2024-04-02
  • MongoDB中实现原理是什么
    今天就跟大家聊聊有关MongoDB中实现原理是什么,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。主流程MyCAT Server 接收 MySQL C...
    99+
    2024-04-02
  • Linux中DHCP的原理是什么
    这篇文章主要介绍“Linux中DHCP的原理是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Linux中DHCP的原理是什么”文章能帮助大家解决问题。DHCP(Dynamic Host Conf...
    99+
    2023-06-27
  • Servlet中Filter的实现原理是什么
    这篇文章主要讲解了“Servlet中Filter的实现原理是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Servlet中Filter的实现原理是什么”...
    99+
    2024-04-02
  • openfiler中iSCSI的实现原理是什么
    这篇文章将为大家详细讲解有关openfiler中iSCSI的实现原理是什么,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。iSCSI概述iSCSI:Internet 小型计算机系统接口 (iS...
    99+
    2023-06-13
  • Golang中 WaitGroup的实现原理是什么
    这篇文章给大家介绍Golang中 WaitGroup的实现原理是什么,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。1 前言WaitGroup是Golang应用开发过程中经常使用的并发控制技术。WaitGroup,可理解...
    99+
    2023-06-19
  • Python中hook的实现原理是什么
    在Python中,hook(钩子)是一种机制,允许开发者在特定事件(例如函数调用、异常发生等)发生时插入自定义的代码进行处理。实现原...
    99+
    2023-09-26
    Python
  • CSS中Scoped的实现原理是什么
    这篇“CSS中Scoped的实现原理是什么”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“CSS中Scoped的实现原理是什么...
    99+
    2023-07-04
  • Python中Dict实现的原理是什么
    1.无序Dict的实现Dict能够快速查找key,这归功于它采用的空间换时间策略和哈希表实现。的在读取和写入Key时, 都会对Key进行哈希计算(所以要求Key都是不可变类型,如果是可变类型,就无法计算出他的哈希值了), 然后根据计算的值,...
    99+
    2023-05-19
    Python dict
  • Golang中map的实现原理是什么
    这篇“Golang中map的实现原理是什么”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Golang中map的实现原理是什么...
    99+
    2023-07-05
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作