`
jinghuainfo
  • 浏览: 1526567 次
  • 性别: Icon_minigender_2
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

用inotify监视文件/目录变化

 
阅读更多

inotify监视文件/目录变化

转载时请注明出处和作者联系方式:http://blog.csdn.net/absurd

作者联系方式:李先静 <xianjimli at hotmail dot com>

更新时间:2007-6-18

介绍inotify使用方法的文章已经有很多了,写得也非常清楚,本来不需要我多此一举了。不过,我是第一次使用,而且用得不是很顺,作为新手,想法毕竟有些不同,所以有些东西还是值得记录下来的。

最近为桌面增加监控applictions目录变化的功能,我们的桌面虽然是自己开发的,但遵循了freedesktop的Desktop Entry Specification标准。应用程序的desktop文件放置在applictions目录下,这是应用程序的入口,桌面负责把它们放在适当的位置(如开始菜单和状态栏中)。对于内置的应用程序,它们的desktop文件不会变化,但是第三方的应用程序可能随时安装/卸载,如果安装/卸载要强迫用户重起机器,那太不人性化了。为了支持动态安装和卸载,我们通过监控applictions中desktop文件的变化来实现。

1. glibc版本偏旧,没有提供inotify的头文件。

较旧的glibc(如2.4之前的)没有提供inotify的头文件,不能直接使用网上介绍的方法,要自己定义系统调用和那些常量,如:

#include <sys/syscall.h>

#ifndef __NR_inotify_init

#if defined(__i386__)

# define __NR_inotify_init 291

# define __NR_inotify_add_watch 292

# define __NR_inotify_rm_watch 293

#elif defined(__x86_64__)

...

{

return syscall(__NR_inotify_init);

}

static inline int inotify_add_watch(int fd, const char *name, uint32_t mask)

{

return syscall(__NR_inotify_add_watch, fd, name, mask);

}

static inline int inotify_rm_watch(int fd, uint32_t wd)

{

return syscall(__NR_inotify_rm_watch, fd, wd);

}

struct inotify_event {

int wd;

uint32_t mask;

uint32_t cookie;

uint32_t len;

char name[];

};

/* the following are legal, implemented events that user-space can watch for */

#define IN_ACCESS 0x00000001 /* File was accessed */

#define IN_MODIFY 0x00000002 /* File was modified */

#define IN_ATTRIB 0x00000004 /* Metadata changed */

#define IN_CLOSE_WRITE 0x00000008 /* Writtable file was closed */

#define IN_CLOSE_NOWRITE 0x00000010 /* Unwrittable file closed */

#define IN_OPEN 0x00000020 /* File was opened */

#define IN_MOVED_FROM 0x00000040 /* File was moved from X */

#define IN_MOVED_TO 0x00000080 /* File was moved to Y */

#define IN_CREATE 0x00000100 /* Subfile was created */

#define IN_DELETE 0x00000200 /* Subfile was deleted */

#define IN_DELETE_SELF 0x00000400 /* Self was deleted */

#define IN_MOVE_SELF 0x00000800 /* Self was moved */

Hal里有一套定义,我验证过没有问题,直接拿来用就好了,可以省不少麻烦。你可以从http://freedesktop.org/~david/dist/hal-0.5.9.tar.gz获取。

2. inotify_fd中读出的buffer可能有多个inotify_event,可以按下列方法一一取出:

inotify_event的长度不是固定的,要根据它的len成员计算它的实际大小,然后找到下一个的开始位置。

static void inotify_events_io_func (GIOChannel *channel, GIOCondition condition, gpointer data)

{

char buf[1024] = {0};

struct inotify_event* event = {0};

int index = 0;

int len = 0;

int fd = g_io_channel_unix_get_fd (channel);

while(((len = read (fd, &buf, sizeof (buf))) < 0) && (errno == EINTR));

while(index < len)

{

event = (struct inotify_event*)(buf+index);

handle_inotify_event(event, data);

index += sizeof(struct inotify_event) + event->len;

g_debug("len=%d index=%d", len, index);

}

return;

}

3. g_main_loop关联以简化实现。

应用程序有自己的事情要做,不能一直挂到inotify_fd上,可以与g_main_loop关联起来,方法如下。

int main(int argc, char* argv[])

{

if(argc != 2)

{

printf("usage: %s dir/n", argv[0]);

return 0;

}

int fd = 0;

const char* dir = argv[1];

GIOChannel *channel = NULL;

fd = inotify_init ();

int wd = inotify_add_watch (fd, dir, IN_MODIFY | IN_CREATE | IN_DELETE | IN_MOVED_FROM | IN_MOVED_TO);

channel = g_io_channel_unix_new (fd);

g_io_add_watch(channel, G_IO_IN, (GIOFunc) inotify_events_io_func, (gpointer)dir);

GMainLoop* loop = g_main_loop_new(NULL, FALSE);

g_main_loop_run(loop);

return 0;

}

4. 处理事件。

事件处理与具体应用有关,只要清楚inotify_event结构中各个成员的意义即可。常用的有三个:mask成员标识变化的类型,name成员标识变化的文件名,wd成员是前面inotify_add_watch返回的值,用它可以映射到目录名(自己建映射关系)。

static void handle_inotify_event(struct inotify_event* event, gpointer data)

{

const char* action = NULL;

switch(event->mask)

{

case IN_MODIFY:

{

action = "IN_MODIFY";

break;

}

case IN_CREATE:

{

action = "IN_CREATE";

break;

}

case IN_DELETE:

{

action = "IN_DELETE";

break;

}

case IN_MOVED_FROM:

{

action = "IN_MOVED_FROM";

break;

}

case IN_MOVED_TO:

{

action = "IN_MOVED_TO";

break;

break;

}

default:break;

}

g_debug("%s: wd=%x mask=%x cookie=%x len=%x %s/%s", action,

event->wd, event->mask, event->cookie, event->len, (char*)data, event->name);

return;

}

5. 小心文件内容更新没有完成。

在测试过程中,我发现在事件处理函数中读取文件内容时,有时文件内容是残缺的,可能是文件内容更新还完全完成。对此,我还没有想到好的方法,目前只是简单的usleep(100)

~~end~~

分享到:
评论

相关推荐

    用inotify监视文件目录变化

    用inotify监视文件目录变化 用inotify监视文件目录变化 用inotify监视文件目录变化 用inotify监视文件目录变化 用inotify监视文件目录变化

    inotify linux 的文件夹监视

    这是监视文件夹变化的程序,指定监视的文件夹类型

    Linux inotify监听文件状态的操作方法

    Inotify 是一个 Linux特性,它监控文件系统操作,比如读取、写入和创建。这篇文章给大家介绍了Linux inotify监听文件状态的相关知识,需要的朋友参考下吧

    redhat8 inotify-tools(x86-64)

    Inotify,它是在内核 2.6.13 版本中引入的一个新功能,它为用户态监视文件系统的变化提供了强大的支持,允许监控程序打开一个独立文件描述符,并针对事件集监控一个或者多个文件,例如打开、关闭、移动/重命名、删除...

    redhat9 inotify-tools(x86-64)

    Inotify,它是在内核 2.6.13 版本中引入的一个新功能,它为用户态监视文件系统的变化提供了强大的支持,允许监控程序打开一个独立文件描述符,并针对事件集监控一个或者多个文件,例如打开、关闭、移动/重命名、删除...

    go-fswatch:fswatch是一个go库,用于监视不依赖于inotify的文件系统更改

    fswatch是一个go库,用于递归地查看文件系统的变化,该变化不依赖于inotify,因此不受操作系统ulimit的限制。 动机 为什么不使用 ? 即使有像这样的很棒的库都提供跨平台文件系统更改通知,但当您要查看大量文件或...

    inotify_simple:一个简单的围绕inotify的Python包装器。 没有花哨的花哨,只有带有ctypes的文字包装器

    inotify_add_watch()和inotify_rm_watch()完全没有任何变化,获取并返回了希望由调用代码跟踪自身的监视描述符整数,就像一个人会使用C中的inotify 。适用于Python 2.7和Python&gt; = 3.2 。 | | 安装 安装inotify_...

    解决Webpack 热部署检测不到文件变化的问题

    调研了一下,原来 Webpack 的热部署功能是使用 inotify 来监视文件变化,其中 fs.inotify.max_user_watches 表示同一用户同时可以添加的watch数目(watch一般是针对目录,决定了同时同一用户可以监控的目录数量) ...

    简单了解Python下用于监视文件系统的pyinotify包

    主要介绍了Python下用于监视文件系统的pyinotify包,pyinotify基于inotify事件驱动机制,需要的朋友可以参考下

    nimwatch:Nim的文件系统监视库

    nimwatch:Nim的文件系统监视库

    Selfpublog:自发布博客工具

    该工具可以监视指定文件夹中的文件更改,并将新添加(修改)的降价文件转换为html文件,以便可以直接访问网页这个工具能监控指定文件夹下的文件变化,将您添加(修改)的markdown文件转为html文件,使网页可以直接...

    janet-lang.org:janet的网站

    要监视更改,请使用make watch 。 服务于localhost:8000 make run 创作内容 内容目录中.mdz扩展名为.mdz页面都将由mendoza解析,并转换为具有相同名称但扩展名为.html的html文件。 标记语言类似于Racket文档工具 ...

Global site tag (gtag.js) - Google Analytics