从inotify机制说到FileObserver实现原理

本文详细介绍了Linux的inotify机制,包括其监控事件类型、API使用和事件处理流程,并探讨了Android中FileObserver的实现原理,从监控线程初始化、启动监控到停止监控的完整过程,以及如何在实际应用中使用FileObserver进行文件监控,并提出了使用时的注意事项。
摘要由CSDN通过智能技术生成

有些情况下,我们难免需要监控一些文件的变化情况,这该如何实现呢?自然而然的我们会想要利用一个线程,每个一段时间便去看看文件的情况,这种方式本质上就是基于时间调度的轮训.虽然能够实现我们的需求,但是这种方式只适合文件经常变化的情况,其他情况下都非常低效,并且可能丢掉某些类型的变化,也就是说,这种方式无法实现实时的文件监控.

inotify简介

那还有其他的方式么?熟悉linux的童鞋应该记得从linux kernel 2.6.13开始引入inotify机制,用于通知用户相关文件变化情况:任何一个文件发生某种变化,都会产生一个相应的文件事件.

我们不仅好奇,文件的哪些事件能够被监控,也就是说inotify支持监控文件的哪些变化呢?继续往下看.

可监控事件类型

目前inotify能够监控的以下文件变化事件:

事件类型 说明
IN_ACCESS 文件被访问
IN_MODIFY 文件被修改
IN_ATTRIB 文件属性被修改
IN_CLOSE_WRITE 可写文件被关闭
IN_CLOSE_NOWRITE 不可写文件被关闭
IN_CLOSE 文件被关闭,也就以上两者的集合
IN_OPEN 文件被打开
IN_MOVED_FROM 文件被移来
IN_MOVED_TO 文件被移走
IN_MOVE 文件被移动,也就是以上两者的集合
IN_CREATE 文件被创建
IN_DELETE 文件被删除
IN_DELETE_SELF 自删除,也就是一个可执行文件在执行时尝试删除自己
IN_MOVE_SELF 自移动,也就是一个可执行文件在执行时尝试移动自己
IN_UNMOUNT 宿主文件系统被卸载

API说明

不难发现,inotify对文件监控的支持是非常全面的,足以满足我们绝大部门的需求.接下来,我们对innotify的api做个简单的说明:

方法 说明
inotify_init 用于创建一个inotify实例,返回一个指向该实例的的文件描述符
inotify_add_watch 添加对文件或者目录的监控,可以指定需要监控那些文件变化事件
inotify_rm_watch 从监控列表中移除监控文件或者目录
read 读取事件信息
close 关闭文件描述符,并会移除所有在该描述符上监控

事件通知

在可监控事件中,我们已经了解inotify支持的文件事件.现在来看看这些当这些文件事件产生时,其发出通知的结构.在inotify中,事件通知结构用结构体inotify_event表示:

struct inotify_event
{
  int wd;               //监控目标的watch描述符
  uint32_t mask;        //事件掩码
  uint32_t cookie;      //事件同步cookie
  uint32_t len;         //name字符串的长度
  char name __flexarr;  //被监视目标的路径名
  };

这里需要记住一点:name字段并不是什么时候都有的:只有要监控的目标是一个目录,且产生的事件与目录内部的文件或子目录相关,且与目录本身无关时才会提供相应的name字段.
cookie用于关联被观察对象的IN_MOVED_FROM事件和IN_MOVED_TO 事件.

使用流程

了解以上之后,那么该怎么用呢?要实现对文件或者目录的监控需要经过以下几个步骤:

1. 创建inotify实例

在应用程序中,首先需要创建inotify实例:

int fd=inotify_init(); 

该方法创建了一个inotify实例,并返回一个文件描述符以便能够通过这个描述符访问到inotify实例.

2. 添加监控

在获得inotify实例产生的文件描述符之后,我们就可以为其添加watch.另外,我们也可以使用mask(事件掩码)来设置我们想监控的事件类型.当然可以我们也可以使用IN_ALL_EVENTS监控所有事件:

int wd=inotify_add_watch(fd,path,mask)

补充:
此处的fd即inotify_init()方法返回的文件描述符.每个文件描述符都有一个排序的事件序列.path则是需要监控的文件或者目录的路径.mask则是事件掩码,它表示应用程序对哪些事件感兴趣.

文件系统产生的事件由Watch对象来管理,该方法将返回的wd就是Watch对象的句柄.

3. 等待事件与循环处理

在为inotify实例添加watch之后,接下来就是等待事件了.为了能不断的处理事件,我们将其放在循环体当中.
在循环中,通过read()方法可以一次获得多个事件.在没有事件产生时,read()被阻塞,一旦有事件产生,那么我们就可以读取事件到的我们设置的事件数组中,然后对事件数组进行处理,其简单代码如下:

//事件数组,自定义设置,这里我们设置为128
char event_buf[128];

while(true){
     int 
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值