根据 inotify 自己开发软件监控文件系统活动

了解 inotify

Inotify 是一个 Linux 内核特性,它监控文件系统,并且及时向专门的应用程序发出相关的事件警告,比如删除、读、写和卸载操作等。您还可以跟踪活动的源头和目标等细节。
使用 inotify 很简单:创建一个文件描述符,附加一个或多个监视器(一个监视器 是一个路径和一组事件),然后使用 read() 方法从描述符获取事件信息。read() 并不会用光整个周期,它在事件发生之前是被阻塞的。
更好的是,因为 inotify 通过传统的文件描述符工作,您可以利用传统的 select() 系统调用来被动地监控监视器和许多其他输入源。两种方法 — 阻塞文件描述符和使用 select()— 都避免了繁忙轮询。
现在,让我们深入了解 inotify,写一些 C 代码,然后看看一组命令行工具,您可以构建并使用它们将命令和脚本附加到文件系统事件。Inotify 不会在中途失去控制,但它可以运行 cat 和 wget,并且在必要时严格执行。
要使用 inotify,您必须具备一台带有 2.6.13 或更新内核的 Linux 机器(以前的 Linux 内核版本使用更低级的文件监控器 dnotify)。如果您不知道内核的版本,请转到 shell,输入 uname -a:
% uname -a
Linux ubuntu-desktop 2.6.24-19-generic #1 SMP ... i686 GNU/Linux
如果列出的内核版本不低于 2.6.13,您的系统就支持 inotify。您还可以检查机器的 /usr/include/sys/inotify.h 文件。如果它存在,表明您的内核支持 inotify。
注意:FreeBSD 和 Mac OS X 提供一个类似于 inotify 的 kqueue。在 FreeBSD 机器上输入 man 2 kqueue 获取更多信息。
本文基于 Ubuntu Desktop version 8.04.1(即 Hardy),它运行在 Mac OS X version 10.5 Leopard 的 Parallels Desktop version 3.0。

inotify C API

Inotify 提供 3 个系统调用,它们可以构建各种各样的文件系统监控器:
inotify_init() 在内核中创建 inotify 子系统的一个实例,成功的话将返回一个文件描述符,失败则返回 -1。就像其他系统调用一样,如果 inotify_init() 失败,请检查 errno 以获得诊断信息。
顾名思义,inotify_add_watch() 用于添加监视器。每个监视器必须提供一个路径名和相关事件的列表(每个事件由一个常量指定,比如
IN_MODIFY)。要监控多个事件,只需在事件之间使用逻辑操作符或 — C 语言中的管道线(|)操作符。如果
inotify_add_watch() 成功,该调用会为已注册的监视器返回一个惟一的标识符;否则,返回
-1。使用这个标识符更改或删除相关的监视器。
inotify_rm_watch() 删除一个监视器。
此外,还需要 read()
和 close() 系统调用。如果描述符由 inotify_init() 生成,则调用 read()
等待警告。假设有一个典型的文件描述符,应用程序将阻塞对事件的接收,这些事件在流中表现为数据。文件描述符上的由 inotify_init()
生成的通用 close() 删除所有活动监视器,并释放与 inotify
实例相关联的所有内存(这里也用到典型的引用计数警告。与实例相关联的所有文件描述符必须在监视器和 inotify 消耗的内存被释放之前关闭)。
这个强大的工具提供 3 个应用程序编程接口(API)调用,以及简单、熟悉的范例 “所有内容都是文件”。现在,我们看看示例应用程序。
示例应用程序:事件监控
清单 1 是一个监控两个事件的目录的简短 C 程序:文件的创建和删除。
清单 1. 简单的 inotify 应用程序,它监控创建、删除和修改事件的目录
#include
#include
#include
#include <sys/types.h>
#include <sys/inotify.h>

#define EVENT_SIZE ( sizeof (struct inotify_event) )
#define BUF_LEN ( 1024 * ( EVENT_SIZE + 16 ) )

int main( int argc, char **argv )
{
int length, i = 0;
int fd;
int wd;
char buffer[BUF_LEN];

fd = inotify_init();

if ( fd < 0 ) {
perror( "inotify_init" );
}

wd = inotify_add_watch( fd, "/home/strike",
IN_MODIFY | IN_CREATE | IN_DELETE );
length = read( fd, buffer, BUF_LEN );

if ( length < 0 ) {
perror( "read" );
}

while ( i < length ) { struct inotify_event *event = ( struct inotify_event * ) &buffer[ i ]; if ( event->len ) {
if ( event->mask & IN_CREATE ) {
if ( event->mask & IN_ISDIR ) {
printf( "The directory %s was created.\n", event->name );
}
else {
printf( "The file %s was created.\n", event->name );
}
}
else if ( event->mask & IN_DELETE ) {
if ( event->mask & IN_ISDIR ) {
printf( "The directory %s was deleted.\n", event->name );
}
else {
printf( "The file %s was deleted.\n", event->name );
}
}
else if ( event->mask & IN_MODIFY ) {
if ( event->mask & IN_ISDIR ) {
printf( "The directory %s was modified.\n", event->name );
}
else {
printf( "The file %s was modified.\n", event->name );
}
}
}
i += EVENT_SIZE + event->len;
}

( void ) inotify_rm_watch( fd, wd );
( void ) close( fd );

exit( 0 );
}
这个应用程序通过 fd = inotify_init(); 创建一个 inotify 实例,并添加一个监视器来监控修改、新文件和
/home/strike 中的损坏文件(由 wd = inotify_add_watch(...) 指定)。read()
方法在一个或多个警告到达之前是被阻塞的。警告的详细内容 — 每个文件、每个事件 —
是以字节流的形式发送的;因此,应用程序中的循环将字节流转换成一系列事件结构。
在文件 /usr/include/sys/inotify.h. 中,您可以找到事件结构的定义,它是一种 C 结构,如清单 2 所示。
清单 2. 事件结构的定义
struct inotify_event
{
int wd; /* The watch descriptor */
uint32_t mask; /* Watch mask */
uint32_t cookie; /* A cookie to tie two events together */
uint32_t len; /* The length of the filename found in the name field */
char name __flexarr; /* The name of the file, padding to the end with NULs */
}
wd 字段是指与事件相关联的监视器。如果每个 inotify 有一个以上的实例,您可以使用这个字段确定如何继续以后的处理过程。mask 字段由几个部分组成,它说明发生的事情。分别测试每个部分。
当把一个文件从一个目录移动到另一个目录时,您可以使用 cookie 将两个事件绑在一起。仅当您监视源和目标目录时,inotify
才生成两个移动事件 — 分别针对源和目标 —,并通过设置 cookie 将它们绑定在一起。要监视一个移动操作,必须指定
IN_MOVED_FROM 或 IN_MOVED_TO,或使用简短的 IN_MOVE,它可以监视两个操作。使用 IN_MOVED_FROM 和
IN_MOVED_TO 来测试事件类型。
最后,name 和 len 包含文件的名称(但不包括路径)和受影响文件的名称的长度。
构建示例应用程序代码
要构建这些代码,请将目录 /home/strike 更改到您的主目录,即将这些代码保存到一个文件中,然后调用 C 编译器 — 在大部分 Linux 系统中为 gcc。然后,运行这个可执行文件,如清单 3 所示。
清单 3. 运行可执行文件
% cc -o watcher watcher.c
% ./watcher
在监视程序运行时,打开第二个终端窗口并使用 touch、cat 和 rm 来更改主目录的内容,如清单 4 所示。完成之后,重新启动您的新应用程序。
清单 4. 使用 touch、cat 和 rm
% cd $HOME
% touch a b c
The file a was created.
The file b was created.
The file c was created.

% ./watcher &
% rm a b c
The file a was deleted.
The file b was deleted.
The file c was deleted.

% ./watcher &
% touch a b c
The file a was created.
The file b was created.
The file c was created.

% ./watcher &
% cat /etc/passwd >> a
The file a was modified.

% ./watcher &
% mkdir d
The directory d was created.
试用其他可用的监视标志。要捕捉权限的更改,请将 IN_ATTRIB 添加到 mask。
使用 inotify 的技巧
您还可以使用 select()、pselect()、poll() 和 epoll()
来避免阻塞。如果您想将监视器的监控作为图形应用程序的主事件处理循环的一部分,或作为监视其他输入连接的守护进程的一部分,这是很有用的。将该
inotify 描述符添加到这组描述符中,进行并发监控。清单 5 展示了 select() 的标准形式。
清单 5. select() 的标准形式
int return_value;
fd_set descriptors;
struct timeval time_to_wait;

FD_ZERO ( &descriptors );
FD_SET( ..., &descriptors );
FD_SET ( fd, &descriptors );

...

time_to_wait.tv_sec = 3;
time.to_waittv_usec = 0;

return_value = select ( fd + 1, &descriptors, NULL, NULL, &time_to_wait);

if ( return_value < 0 ) {
/* Error */
}

else if ( ! return_value ) {
/* Timeout */
}

else if ( FD_ISSET ( fd, &descriptors ) ) {
/* Process the inotify events */
...
}

else if ...
select() 方法在 time_to_wait 期间暂停程序。然而,如果在这个延迟期间这组描述符的任意一个文件描述符发生活动,将立即恢复执行程序。否则,调用就会超时,允许应用程序执行其他进程,比如在图形用户界面(GUI)工具中响应鼠标或键盘事件。
下面是使用 inotify 的其他技巧:
如果监视中的文件或目录被删除,它的监视器也会被自动删除(在删除事件发出之后)。
如果在已卸载的文件系统上监控文件或目录,监视器将在删除所有受影响的监视之前收到一个卸载事件。
将 IN_ONESHOT 标志添加到监视器标记中,设置一个一次性警告。警告在发送之后将被删除。
要修改一个事件,必须提供相同的路径名和不同的标记。新监视器将取代老监视器。
考虑到实用性,不可能耗尽任何一个 inotify 实例的监视器。然而,您可能会耗尽事件队列的空间,这取决于处理事件的频率。队列溢出会引起 IN_Q_OVERFLOW 事件。
close() 方法毁坏 inotify 实例和所有相关联的监视器,并清空队列中的所有等待事件。

根据 inotify 自己开发软件监控文件系统活动

时间: 2024-10-08 08:19:20

根据 inotify 自己开发软件监控文件系统活动的相关文章

(转)Linux下通过rsync与inotify(异步文件系统事件监控机制)实现文件实时同步

Linux下通过rsync与inotify(异步文件系统事件监控机制)实现文件实时同步原文:http://www.summerspacestation.com/linux%E4%B8%8B%E9%80%9A%E8%BF%87rsync%E4%B8%8Einotify%E5%BC%82%E6%AD%A5%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F%E4%BA%8B%E4%BB%B6%E7%9B%91%E6%8E%A7%E6%9C%BA%E5%88%B6%E5%AE%9E

python软件开发规范&amp;分文件对于后期代码的高效管理

根据本人的学习,按照理解整理和补充了python模块的相关知识,希望对于一些需要了解的python爱好者有帮助! 一.软件开发规范--分文件 当代码存在一个py文件中时: 1.不便于管理 (修改,增加) 2.可读性差 3.加载速度慢 Django--雏形(约定俗称) 1.启动文件 启动接口 2.公共文件 大家需要的功能 3.配置文件(静态文件) 变量 4.主逻辑 核心 5.用户相关数据 账号和密码等文件 6.日志 记录主要信息,记录开发人员的行为 高内聚 二.sys sys python解释器做

Web开发安全之文件上传安全

很长一段时间像我这种菜鸡搞一个网站第一时间反应就是找上传,找上传.借此机会把文件上传的安全问题总结一下. 首先看一下DVWA给出的Impossible级别的完整代码: <?php if( isset( $_POST[ 'Upload' ] ) ) { // Check Anti-CSRF token checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' ); // File informa

开发进阶09_xib文件的基本使用_File&#39;s Owner

storyboard:描述软件界面,大范围,重量级,比较适合描述整个软件的所有界面 xib:描述软件界面,小范围,轻量级,比较适合描述某个小界面 两个各有优缺点 //1.加载RowView.xib NSArray *views = [[NSBundle mainBundle] loadNibNamed:@"RowView” owner:self options:nil]; loadNibNamed:从资源中读取xib文件 如果想通过连线的方式去调用头文件中的方法,需要给xib文件设置File’s

Unity3D游戏开发软件破解版安装

怎么获取Unity3D游戏开发软件,笔者在这里就告诉大家一个小技巧,有兴趣的朋友可以继续往下看. 下载Unity3D当然要到官网(建议用迅雷下载),安装后还需要注册,这里就建议大家根据实际情况考虑啦!如果是自己学习研究用,就没必要去购买,完全可以用破解版本;如果是公司开发用,还是买一个为好.注:Unity3D是按功能模块收费的. 没注册过Unity3D游戏开发软件的朋友,可以跟着以下步骤注册.这里我会提供一种破解法,需要破解版安装包的朋友请到菜鸟在线官网上注册并联系客服获取. 1.打开Unity

利用pyinotify监控文件内容,像tailf命令但比它更强

Linux的tail/tailf命令使用了内核提供的inotify功能,下面的Python例子也使用inotify实现比tail/tailf更强的监控文件功能. watchfile.py #!/usr/bin/python import sys, os, pyinotify notifier = None monfile = None lastsize = 0 wm = None wd = 0 def roll_file(filename): global lastsize fd = os.op

zabbix nagios 类nagios 之 不以性能为前提的开发和监控都是瞎扯淡

从最初的nagios到现在强大的zabbix 3.0,我想说,不以性能为前提的开发和监控都是瞎扯淡? 首先我对这两款监控软件的认识: zabbix,很多企业都在用,给人的感觉是很炫,不过我个人觉得虽然它功能强大,能绘制出狠酷的图像,但是在你看到他“美丽”面时,是否有想到他对原库.系统的“伤害”,是否有考虑过对于某些指标真的有实际意义. zabbix监控服务器:通过agent将相关数据以json方式插入数据库中,然后通过应用去调取数据库的内容展示出来. zabbix监控数据库:通过数据库用户(授予

iOS游戏开发 软件开发 UNITY3D软件外包 APP定制

iOS游戏开发 软件开发 UNITY3D软件外包 APP定制 软件开发是根据用户要求建造出软件系统或者系统中的软件部分的过程.软件开发是一项包括需求捕捉.需求分析.设计.实现和测试的系统工程.软件一般 是用某种程序设计语言来实现的.通常采用软件开发工具可以进行开发.软件分为系统软件和应用软件,并不只是包括可以在计算机上运行的程序,与这些程序相关 的文件一般也被认为是软件的一部分. 软件设计思路和方法的一般过程,包括设计软件的功能和实现的算法和方法.软件的总体结构设计和模块设计.编程和调试.程序联

使用FileSystemWatcher监控文件夹及文件

引言 这一周主要精力集中学习一个同事开发的本地文件搜索项目上,其中客户端添加共享文件时主要是使用FileSystemWatcher 监控文件,并在各种事件发生时向服务器发送消息. 解决方法 FileSystemWatcher类以前也使用过,没有太仔细去观察,这次使用时才发现其事件提示会很有趣: a):当你添加文件或文件夹时,会触发Created事件,然后修改默认文件夹或文件名称再触发Changed事件. b):复制或移动文件夹文件时则是触发Created事件. c):删除文件夹或文件时触发Del