- 浏览: 484441 次
- 性别:
- 来自: 大连
文章分类
最新评论
-
龘龘龘:
TrueBrian 写道有个问题,Sample 1中,为了控制 ...
What's New on Java 7 Phaser -
龘龘龘:
楼主总结的不错。
What's New on Java 7 Phaser -
TrueBrian:
有个问题,Sample 1中,为了控制线程的启动时机,博主实际 ...
What's New on Java 7 Phaser -
liguanqun811:
不知道楼主是否对zookeeper实现的分布式锁进行过性能测试 ...
Distributed Lock -
hobitton:
mysql的get lock有版本限制,否则get lock可 ...
Distributed Lock
1 Overview
最近公司的一个任务需要实时监控文件系统中某个文件的内容变化。由于程序本身由Java编写,因此使用了inotify-java(http://code.google.com/p/inotify-java/)。inotify-java只是对Linux中inotify相关的内核调用进行了封装,因此在使用inotify-java之前有必要了解一下inotify。
inotify是一种基于inode的文件系统监控机制。从2.6.13-rc3版本起被集成到Linux 内核中,作为dnotify的替代。跟dnotify相比,inotify除了更易于使用之外还有以下主要的优点:
- inotify使用异步的事件通知机制。
- 可以监控文件系统中的任何对象(dnotify只能监控目录)。如果inotify监控的是目录,那么在目录中的某个文件发生变化时,inotify可以通知发生变化的文件名(dnotify只能报告有变化,应用程序本身需要判断是哪个文件发生变化)。
- 对于每个被监控的文件,inotify不需要维护一个打开的文件描述符,因此不会影响unmount之类的操作,相反会在被监控文件所在的文件系统被unmount时得到一个通知。
2 inotify
2.1 interfaces
如果C库支持inotify,那么在C程序中直接#include <sys/inotify.h> 即可。
通过int inotify_init (void)系统调用进行初始化。返回值小于0说明调用失败;否则会在内核中创建一个inotify实例,并且返回对应的文件描述符。该文件描述符用于读取inotify事件(inotify event),读取的方式既可以是阻塞式,例如read,也可以是非阻塞式,例如select,poll和epoll(java6已经支持epoll,但是不支持对FileChannel进行select)。
通过int inotify_add_watch (int fd, const char *path, __u32 mask)系统调用添加监控(watch)。参数fd是inotify_init调用返回的文件描述符;参数path是监控对象的路径(文件,目录等);参数mask是期望得到通知的事件类型的位掩码。inotify可以监控以下类型的事件:opens、closes、reads、writes、creates、deletes、moves、metadata changes 和 unmounts。可以向一个inotify实例添加多个监控。该系统调用在成功情况下返回一个监控描述符(watch descriptor),它被用来标识不同的监控。mask参数的可选值如下:
Event | Description |
IN_ACCESS | File was read from. |
IN_MODIFY | File was written to. |
IN_ATTRIB | File's metadata (inode or xattr) was changed. |
IN_CLOSE_WRITE | File was closed (and was open for writing). |
IN_CLOSE_NOWRITE | File was closed (and was not open for writing). |
IN_OPEN | File was opened. |
IN_MOVED_FROM | File was moved away from watch. |
IN_MOVED_TO | File was moved to watch. |
IN_DELETE | File was deleted. |
IN_DELETE_SELF | The watch itself was deleted. |
IN_CLOSE | IN_CLOSE_WRITE | IN_CLOSE_NOWRITE |
IN_MOVE | IN_MOVED_FROM | IN_MOVED_TO |
IN_ALL_EVENTS | Bitwise OR of all events. |
IN_ONESHOT | One shot support |
假设希望监控/home/user1/data.txt文件的读取和修改事件,那么可以使用IN_ACCESS和IN_MODIFY,例如:
int wd; wd = inotify_add_watch (fd, "/home/user1/data.txt", IN_ACCESS | IN_MODIFY);
假设希望只监控/home/user1/data.txt文件的修改事件一次,那么可以使用IN_MODIFY 和IN_ONESHOT,例如:
int wd; wd = inotify_add_watch (fd, "/home/user1/data.txt", IN_MODIFY | IN_ONESHOT);
通过int inotify_rm_watch (int fd, int wd)系统调用移除监控。参数fd是inotify_init调用返回的文件描述符;参数wd是要被移除的监控描述符。如果调用成功,那么返回0;否则返回负值。
通过int close (int fd)系统调用销毁inotify实例,以及关联的所有监控和未决事件。参数fd是inotify_init调用返回的文件描述符。
2.2 configuration
inotify可以通过procfs和sysctl进行配置。/proc/sys/fs/inotify/目录下有以下三个文件:
- max_queued_events 最大排队的事件个数。如果排队事件个数达到此值,那么新到的时间会被丢弃,并发送IN_Q_OVERFLOW事件。默认值16,384。
- max_user_instances 每个用户可以创建的inotify实例最大值。默认值128。
- max_user_watches 每个用户可以创建的监控的最大值。默认值8,192。
2.3 notifications
inotify的事件是异步通知的,并且在内部进行了排队。但是对事件的读取必须以同步方式进行。如果以read读取,那么该方法一直阻塞到有事件到达,并且一次会读入所有排队中的事件。inotify的通知事件由inotify_event结构体定义,如下:
struct inotify_event { __s32 wd; /* watch descriptor */ __u32 mask; /* watch mask */ __u32 cookie; /* cookie to synchronize two events */ __u32 len; /* length (including nulls) of name */ char name[0]; /* stub for possible name */ };
其中wd是监控描述符,跟调用inotify_add_watch()时返回的监控描述符对应。如果应用程序想知道与之对应的文件,那么应用程序本身需要建立监控描述符和文件之间的对应关系;mask是事件的位掩码;cookie用于关联两个独立的事件(例如IN_MOVED_FROM和IN_MOVED_TO事件);len是name的长度;name是发生事件的对象名,如果监控的是目录,那么name是发生事件的文件名。如果监控的是文件,那么name是null。
如果被监控的目录或者文件被unmount卸载,那么inotify会发送IN_UNMOUNT。假设监控对象是个目录,如果将被监控目录中某个文件移动到被监控目录外,那么inotify会发送IN_MOVED_FROM事件;如果将被监控目录外的某个文件移动到被监控目录中,那么inotify会发送IN_MOVED_TO;如果将被监控目录中的某个文件改名(即移动到相同目录中),那么inotify会发送IN_MOVED_FROM和IN_MOVED_TO两个事件,并且这两个事件的cookie相同。
需要注意的是,如果使用vi对被监控的文件进行编辑,那么不会得到IN_MODIFY事件,而是会得到IN_DELETE_SELF、IN_MOVE_SELF和IN_IGNORED三个事件。这是因为vi其实是在一个副本上进行编辑,保存的时候将原文件覆盖。收到IN_IGNORED事件说明监控已经自动地从inotify实例中移除(由于监控对象已经被删除,或者所在的文件系统被unmount)。由于监控已被移除,所以inotify实例以后也不会再发送此文件相关的任何事件。
3 inotify-java
inotify-java并不复杂,每个Inotify实例都会创建两个线程:readerThread和queueThread。readerThread在循环中调用native read方法接收事件,并将接收到的事件放入BlockingQueue中。queueThread从BlockingQueue中take事件,回调InotifyEventListener。
inotify-java使用起来也比较简单。首先需要实例化inotify对象(在其构造函数中会调用System.loadLibrary("inotify-java"));然后在inotify对象上注册InotifyEventListener;最后通过inotify对象的addWatch方法添加监控即可。以下是段示例代码:
import java.util.HashMap; import java.util.Map; import com.den_4.inotify_java.Constants; import com.den_4.inotify_java.EventQueueFull; import com.den_4.inotify_java.Inotify; import com.den_4.inotify_java.InotifyEvent; import com.den_4.inotify_java.InotifyEventListener; public class Test { // private static final Map<Integer, String> MASKS = new HashMap<Integer, String>(); static { MASKS.put(Constants.IN_ACCESS, "IN_ACCESS"); MASKS.put(Constants.IN_MODIFY, "IN_MODIFY"); MASKS.put(Constants.IN_ATTRIB, "IN_ATTRIB"); MASKS.put(Constants.IN_CLOSE_WRITE, "IN_CLOSE_WRITE"); MASKS.put(Constants.IN_CLOSE_NOWRITE, "IN_CLOSE_NOWRITE"); MASKS.put(Constants.IN_OPEN, "IN_OPEN"); MASKS.put(Constants.IN_MOVED_FROM, "IN_MOVED_FROM"); MASKS.put(Constants.IN_MOVED_TO, "IN_MOVED_TO"); MASKS.put(Constants.IN_CREATE, "IN_CREATE"); MASKS.put(Constants.IN_DELETE, "IN_DELETE"); MASKS.put(Constants.IN_DELETE_SELF, "IN_DELETE_SELF"); MASKS.put(Constants.IN_MOVE_SELF, "IN_MOVE_SELF"); MASKS.put(Constants.IN_UNMOUNT, "IN_UNMOUNT"); MASKS.put(Constants.IN_Q_OVERFLOW, "IN_Q_OVERFLOW"); MASKS.put(Constants.IN_IGNORED, "IN_IGNORED"); MASKS.put(Constants.IN_ONLYDIR, "IN_ONLYDIR"); MASKS.put(Constants.IN_DONT_FOLLOW, "IN_DONT_FOLLOW"); MASKS.put(Constants.IN_MASK_ADD, "IN_MASK_ADD"); MASKS.put(Constants.IN_ISDIR, "IN_ISDIR"); MASKS.put(Constants.IN_ONESHOT, "IN_ONESHOT"); } public static void main(String args[]) { try { Inotify i = new Inotify(); InotifyEventListener e = new InotifyEventListener() { public void filesystemEventOccurred(InotifyEvent e) { System.out.println("inotify event, mask: " + getMask(e.getMask()) + ", name: " + e.getName() + ", now: " + System.currentTimeMillis()); } public void queueFull(EventQueueFull e) { System.out.println("inotify event queue: " + e.getSource() + " is full"); } }; i.addInotifyEventListener(e); i.addWatch("./test/", Constants.IN_MODIFY); } catch (Throwable e) { e.printStackTrace(); } } public static String getMask(int mask) { StringBuilder sb = new StringBuilder(); for(Integer m : MASKS.keySet()) { if((mask & m) != 0) { if(sb.length() > 0) { sb.append("|"); } sb.append(MASKS.get(m)); } } return sb.toString(); } }
评论
问一下,AIX下是否有类似的支持?
发表评论
-
Understanding the Hash Array Mapped Trie
2012-03-30 10:36 0mark -
Atomic Bit Operation in Linux Kernel
2012-02-08 00:27 2125Linux Kernel支持atomic bit operat ... -
A Hierarchical CLH Queue Lock
2012-01-14 19:01 2152A Hierarchical CLH Queue Lock ( ... -
Inside AbstractQueuedSynchronizer (4)
2012-01-08 17:06 3527Inside AbstractQueuedSynchroniz ... -
Inside AbstractQueuedSynchronizer (3)
2012-01-07 23:37 4755Inside AbstractQueuedSynchroniz ... -
Inside AbstractQueuedSynchronizer (2)
2012-01-07 17:54 6371Inside AbstractQueuedSynchroniz ... -
Inside AbstractQueuedSynchronizer (1)
2012-01-06 11:04 7953Inside AbstractQueuedSynchroniz ... -
Code Optimization
2011-10-14 00:11 1613当前开发人员在进行编码的时候,可能很少关注纯粹代码级别的优化了 ... -
Several Frequently Used Commands
2011-10-13 11:35 1185sed '/^\s*$/d' a.txt # delete A ... -
Distributed Lock
2011-08-02 22:02 92171 Overview 在分布式系统中,通常会 ... -
What's New on Java 7 Phaser
2011-07-29 10:15 82871 Overview Java 7的并 ... -
Sequantial Lock in Java
2011-06-07 17:00 22231 Overview Linux内核中常见的同步机 ... -
Linux Readling List
2011-05-24 22:51 1141Linux in a Nutshell Linux Syst ... -
Feature or issue?
2011-04-26 22:23 121以下代码中,为何CglibTest.intercept ... -
Bloom Filter
2010-10-19 00:41 50811 Overview Bloom filt ... -
Inside java.lang.Enum
2010-08-04 15:40 64831 Introduction to enum J ... -
Open Addressing
2010-07-07 17:59 34811 Overview Open addressi ... -
JLine
2010-06-17 09:11 11014Overview JLine 是一个用来处理控 ... -
ID Generator
2010-06-14 14:45 1684关于ID Generator,想 ... -
Perf4J
2009-06-11 23:13 84941 Overview Perf4j是一个用于计算 ...
相关推荐
《深入解析inotify-java-2.1源码》 在Java世界中,对文件系统事件的监听是一项重要的功能,尤其在构建实时系统或者监控服务时。`inotify-java`库为Java开发者提供了一个方便的接口,用于访问Linux系统的inotify机制...
本资源是使用Ant工具构建成的jar包,你也可以在inotify-java官方网站或其GitHub中下载源代码并自行使用Ant打包(需要注意的是你在使用Ant打包时需要将解压目录下src/java下的builder.xml中build操作jar属性的basedir...
关于源码包`nbargnesi-inotify-java-27510bee4b9a`,这很可能是`inotify-java`项目的Git仓库的一个特定版本。如果你需要查看或修改源码,或者编译自定义版本的jar包,可以解压这个文件并使用Git或源码构建工具进行...
inotify能够对文件系统进行监控,书上举的例子都是c++使用inotify的例子,难道没有Java版吗,肯定有,只不过要自己编译,在网上找到别人的博客有,但是人家不愿意分享,我就只能自己编译了,压缩包里有编译好的jar包...
java用于监控Linux下文件变化的工具包,包含文件写完成事件,使用方法: Inotify i = new Inotify(); int wd = i.addWatch(dir.getPath(), Close_Write); i.addListener(wd, new InotifyEventListener() { //实现 }...
本资源"**inotify-java-2.1.zip**"包含了Java版的Inotify接口实现——Inotify.jar,以及必要的本地库(so文件),使Java开发者能够利用Inotify功能来监听文件系统的各种事件。 Inotify的主要优势在于,它减少了应用...
### inotify手册:深入了解文件系统监控 #### 一、引言 `inotify`是Linux内核中的一个重要特性,主要用于监控文件系统的变化。通过`inotify`,开发人员可以编写自己的应用程序来监听文件或目录的变化事件,如创建、...
Usage: $ java -jar hdfs-inotify-example-uber.jar <HDFS> [] 这是一个快速而肮脏的例子。 如果省略TxId arg,如下所示: $ sudo -u hdfs java -jar hdfs-inotify-example-uber.jar hdfs://brooklyn.onefoursix....
实用的木偶查看器 简单的人偶信息 UI 有关 Puppet 的信息,请参阅: : 职能: 查看未完成的客户端证书请求 签约优秀客户 查看有关可用客户端的信息 ..../configure --without-inotify --with-fseve
Inotify 是 Linux 内核提供的一种文件系统事件监控机制,它允许程序监控文件或目录的改变,例如创建、删除、修改、移动等。通过使用 Inotify,开发者可以编写出能够实时响应文件系统变动的程序,这在日志监控、同步...
标题中的"storm-hdfs-spout"是一个专门为Apache Storm设计的组件,它利用了HDFS(Hadoop Distributed File System)的INotify API来实现文件系统事件驱动的数据处理。这个组件允许实时数据流处理系统如Storm能够及时...
iNotify platform-admin 后台管理 platform-api 微信小程序商城api接口 platform-common 公共模块 platform-framework 系统WEB合并 platform-gen 代码生成 platform-schedule 定时任务 ...
3. Java:可以使用`jnotify`库,或者在Java 7及以上版本中直接使用`java.nio.file.FileSystems`和`java.nio.file.WatchService`。 4. Go:`fsnotify`库提供了一个简单的接口来监控文件系统事件。 五、实用工具 除了...
- **文件系统监视器**:Capivara使用操作系统提供的文件系统事件API(如Windows的FileSystemWatcher,Unix的inotify)来监听文件变化。 - **网络通信**:通过Java的Socket编程或HTTP/HTTPS协议进行网络通信,确保...
您还需要java才能使用 ,inotify-tools和inotifywait验证工具ebook-polish和ebook-view 。 Kindle导出需要ImageMagick。 复制您的epub电子书,并将其放在Makefile旁边,并将其重命名为current.epub 。 这是该工具...
Java线程轮询,监听/data/data/{package-name}目录是否存在:卸载app,进程退出,线程也被销毁。 C进程轮询,监听/data/data/{package-name}目录是否存在:目前业界普遍采用的方案。 原理 从前四种方案可以看到,...
若要实现数据文件的实时同步,可结合cron定时任务定期运行rsync命令,或者利用inotify-tools监控文件系统事件,一旦有变动就触发同步。 通过以上步骤,您已经成功地在两台计算机节点间部署了rsync并实现了数据文件...
java snmp 源码 Learnease - 在线教学网站 JDK版本: jdk1.8.0_141 openjdk1.8.0.151 服务器系统:CentOS 7 数据库: Mysql 5.7 ### 项目运行前的准备: * #### 安装/配置 CentOS 安装第三方源: epel-release Nux ...