linux c 监视目录文件,linux c监控文件事件

linux c监控文件事件

某些应用程序需要对文件或目录进行监控,来侦测其发生特定事件。例如当文件加入或移出一目录,图形化文件管理器应能判定此目录是否在其当前显示之列,而守护进程可能也要监控自己的配置文件是否修改。

创建新的inotify实例。#include

int inotify_init(void);

//成功返回文件描述符,错误-1

追加新的监控项#include

int inotify_add_watch(int fd, const char *pathname, uint32_t mask);

//返回监控描述符,失败-1

参数pathname标识欲创建或修改的监控项所对应的文件。调用者必须有读的权限(就算后来权限改了,只要注册上了,后面还是会收到事件)。

如果pathname没有加入到fd监控列表则加入,已加入的则修改。参数mask为掩码,定义了欲监控的事件。

5386f26d90eee72ab5f17cea53bafd9d.png

删除由wd指定的监控项,wd是监控描述符,由inotify_add_watch() 返回。删除监控项会为该监控描述符生成 IN_IGNORED 事件。#include

int inotify_rm_watch(int fd, uint32_t wd);

//成功返回0,失败-1

使用inotify_add_watch() 删除或修改监控项时,位掩码参数mask标识了 pathname 要监控的事件。下表 in 列列出可在mask中定义的事件位。

681e70120e29e46f229877d437512d3f.png

读取inotify事件

事件读取可用read() 读取,默认会阻塞,除非设置了 O_NONBLOCK 标志,若设置了且无事件发生,报错 EAGAIN。

事件发生后,每次调用会返回一个缓冲区,内含一个或多了如下结构,缓冲区大小应至少为 sizeof(struct inotify_event) + NAME_MAX + 1 字节。struct inotify_event {

int wd; /* 发生事件的描述符 */

uint32_t mask; /* Bits describing event that occurred */

uint32_t cookie; /* Cookie for related events (for rename()) */

uint32_t len; /* Size of 'name' field */

char name[]; /* Optional null-terminated filename */

};

7db9544b8d02d7ef1498ad2c84dc089f.png

上图是一个有序的队列,字段wd表明是哪个监控描述符,当应用程序要监控同一 inotify 文件描述符下多个文件和目录时,字段wd就非常有用,可以用它来判定发生在哪个目录,哪个文件。不过要做到这一点,必须自己维护监控描述符和路径名之间的关系。

mask 返回描述该事件的位掩码。由表 19-1 out列展示可出现于 mask中的位范围。cookie 字段只有在对文件重命名时才会用到。在待重命名目录产生 IN_MOVED_FROM 事件。目标目录产生 IN_MOVED_TO 事件。如果同一目录,cookie相等。

如果受监控的目录发生事件,name字段以空字符结尾来表示该文件。若为本身,不使用name字段,len为0。

事件队列末尾追加新事件时如果和队列当前尾部事件有相同的wd,mask,cookie,mask则会合并。

队列限制和 /proc 文件

对inotify事件做排队处理要消耗内存。所以内核会施加各种限制。超级用户可以配置 /proc/sys/fs/inotify 路径中的3个文件来调整限制。

max_queued_events inotify实例队列事件数上限。超出系统生成 IN_Q_OVERFLOW 事件,并丢弃多余事件。溢出事件 wd 为-1。

max_user_instances 对每个真实用户id创建的inotify实例数的限制值。

max_user_watches 对每个真实用户id创建的监控项数量的限制值。

例子#include

#include

#include /* Type definitions used by many programs */

#include /* Standard I/O functions */

#include /* Prototypes of commonly used library functions,

plus EXIT_SUCCESS and EXIT_FAILURE constants */

#include /* Prototypes for many system calls */

#include /* Declares errno and defines error constants */

#include /* Commonly used string-handling functions */

static void

displayInotifyEvent(struct inotify_event *i)

{

printf(" wd =%2d; ", i->wd);

if (i->cookie > 0)

printf("cookie =%4d; ", i->cookie);

printf("mask = ");

if (i->mask & IN_ACCESS) printf("IN_ACCESS ");

if (i->mask & IN_ATTRIB) printf("IN_ATTRIB ");

if (i->mask & IN_CLOSE_NOWRITE) printf("IN_CLOSE_NOWRITE ");

if (i->mask & IN_CLOSE_WRITE) printf("IN_CLOSE_WRITE ");

if (i->mask & IN_CREATE) printf("IN_CREATE ");

if (i->mask & IN_DELETE) printf("IN_DELETE ");

if (i->mask & IN_DELETE_SELF) printf("IN_DELETE_SELF ");

if (i->mask & IN_IGNORED) printf("IN_IGNORED ");

if (i->mask & IN_ISDIR) printf("IN_ISDIR ");

if (i->mask & IN_MODIFY) printf("IN_MODIFY ");

if (i->mask & IN_MOVE_SELF) printf("IN_MOVE_SELF ");

if (i->mask & IN_MOVED_FROM) printf("IN_MOVED_FROM ");

if (i->mask & IN_MOVED_TO) printf("IN_MOVED_TO ");

if (i->mask & IN_OPEN) printf("IN_OPEN ");

if (i->mask & IN_Q_OVERFLOW) printf("IN_Q_OVERFLOW ");

if (i->mask & IN_UNMOUNT) printf("IN_UNMOUNT ");

printf("\n");

if (i->len > 0)

printf(" name = %s\n", i->name);

}

#define BUF_LEN (10 * (sizeof(struct inotify_event) + NAME_MAX + 1))

int

main(int argc, char *argv[])

{

int inotifyFd, wd, j;

char buf[BUF_LEN];

ssize_t numRead;

char *p;

struct inotify_event *event;

if (argc < 2 || strcmp(argv[1], "--help") == 0){

printf("%s pathname...\n", argv[0]);

return 1;

}

inotifyFd = inotify_init(); /* Create inotify instance */

if (inotifyFd == -1)

perror("inotify_init");

for (j = 1; j < argc; j++) {

wd = inotify_add_watch(inotifyFd, argv[j], IN_ALL_EVENTS);

if (wd == -1)

perror("inotify_add_watch");

printf("Watching %s using wd %d\n", argv[j], wd);

}

for (;;) { /* Read events forever */

numRead = read(inotifyFd, buf, BUF_LEN);

if (numRead == 0){

printf("read() from inotify fd returned 0!");

return 1;

}

if (numRead == -1)

perror("read");

printf("Read %ld bytes from inotify fd\n", (long) numRead);

/* Process all of the events in buffer returned by read() */

for (p = buf; p < buf + numRead; ) {

event = (struct inotify_event *) p;

displayInotifyEvent(event);

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

}

}

return 0;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值