1. inotifyd
这次看的是busybox源码下的./miscutils/inotifyd.c
-
使用说明:
-
inotifyd PROG FILE1[:MASK]...
-
If PROG is -, events are sent to stdout.
-
Events:
-
a File is accessed
-
c File is modified
-
e Metadata changed
-
w Writable file is closed
-
0 Unwritable file is closed
-
r File is opened
-
D File is deleted
-
M File is moved
-
u Backing fs is unmounted
-
o Event queue overflowed
-
x File can't be watched anymore
-
If watching a directory:
-
m Subfile is moved into dir
-
y Subfile is moved out of dir
-
n Subfile is created
-
d Subfile is deleted
-
-
使用方法:
-
./_install/busybox inotifyd - /tmp/test/1.c:r
-
-
a. 监测文件
-
cong@msi:/tmp/test$ cat 1.c //-->terminal1
-
就会打印:
-
cong@msi:/work/busybox$ ./_install/busybox inotifyd - /tmp/test/1.c:r //-->terminal2先运行
-
r /tmp/test/1.c
-
-
b. 监测目录
-
cong@msi:/tmp/test$ touch 4.c //-->terminal1
-
cong@msi:/work/busybox$ ./_install/busybox inotifyd - /tmp/test/:n //-->terminal2 先运行
-
n /tmp/test/ 4.c
-
-
cong@msi:/tmp/test$ rm 4.c //-->terminal1
-
cong@msi:/work/busybox$ ./_install/busybox inotifyd - /tmp/test/:d //-->terminal2 先运行
-
d /tmp/test/ 4.c
2. 源码
我把./miscutils/inotifyd.c改成了一个独立的小程序
-
cong@msi:/work/test/busytest/14inotify$ cat inotify.c
-
#include "./utils.h"
-
#include <sys/inotify.h>
-
#include <poll.h>
-
#include <sys/ioctl.h> //FIONREAD
-
-
//static const char mask_names[] ALIGN1 =
-
static const char mask_names[] =
-
"a" // 0x00000001 File was accessed
-
"c" // 0x00000002 File was modified
-
"e" // 0x00000004 Metadata changed
-
"w" // 0x00000008 Writable file was closed
-
"0" // 0x00000010 Unwritable file closed
-
"r" // 0x00000020 File was opened
-
"m" // 0x00000040 File was moved from X
-
"y" // 0x00000080 File was moved to Y
-
"n" // 0x00000100 Subfile was created
-
"d" // 0x00000200 Subfile was deleted
-
"D" // 0x00000400 Self was deleted
-
"M" // 0x00000800 Self was moved
-
"\0" // 0x00001000 (unused) //-->\0之后就没有用了,mask=0x0fff也是12位的
-
// Kernel events, always reported:
-
"u" // 0x00002000 Backing fs was unmounted
-
"o" // 0x00004000 Event queued overflowed
-
"x" // 0x00008000 File is no longer watched (usually deleted)
-
;
-
enum {
-
MASK_BITS = sizeof(mask_names) - 1
-
};
-
-
int main(int argc, char **argv)
-
{
-
int n;
-
unsigned mask;
-
struct pollfd pfd;
-
char **watches; // names of files being watched
-
const char *args[5];
-
char eventbuf[1024];
-
-
//argv[1]结果显示的地方,-代表输出到stdout; argv[2]是要监测的文件或目录
-
if (!argv[1] || !argv[2])
-
{
-
printf("usage: inotify - [FILE]:[MASK]\n");
-
return -1;
-
}
-
-
argv++;
-
-
watches = argv;
-
args[0] = *argv;
-
args[4] = NULL;
-
argc -= 2; // number of files we watch
-
-
//a. 创建 inotify实例
-
pfd.fd = inotify_init();
-
if (pfd.fd < 0)
-
dbmsg("no kernel support");
-
-
//这个地方很经典,要详细分析
-
while (*++argv) { //假设参数="/tmp/test/1.c:r"
-
char *path = *argv; //此处path="/tmp/test/1.c:r"
-
char *masks = strchr(path, ':'); //查找:此时masks=:r
-
mask = 0x0fff;
-
if (masks) {
-
*masks = '\0'; //masks=\0r,那么path="/tmp/test/1.c"
-
mask = 0;
-
while (*++masks) { //因为是++masks,所以*masks='r'
-
const char *found;
-
found = memchr(mask_names, *masks, MASK_BITS); //从mask_names[] ="acew0rmyndDm\0uox";中找到r的地址
-
if (found)
-
mask |= (1 << (found - mask_names)); //found-mask_names就是r在mask_names中的第几项,然后移位就是mask
-
}
-
}
-
//b.添加一个watch
-
n = inotify_add_watch(pfd.fd, path, mask);
-
if (n < 0)
-
dbmsg("add watch (%s) failed", path);
-
}
-
//c.poll结构体初始化
-
pfd.events = POLLIN;
-
while (1) {
-
int len;
-
void *buf;
-
struct inotify_event *ie;
-
again:
-
n = poll(&pfd, 1, -1); //d.调用poll轮询监控watch上有没有事件发生
-
if (n < 0 && errno == EINTR) //被信号中断,返回继续等待
-
goto again;
-
if (n <= 0) //真正有error了,就break退出
-
break;
-
ioctl(pfd.fd, FIONREAD, &len); //调用ioctl 命令的FIONREAD 来得到当前队列的长度
-
ie = buf = (len <= sizeof(eventbuf)) ? eventbuf : malloc(len);
-
len = read(pfd.fd, buf, len);
-
//e.下面就处理buffer
-
while (len > 0) {
-
int i;
-
// cache relevant events mask
-
unsigned m = ie->mask & ((1 << MASK_BITS) - 1);
-
if (m) {
-
char events[MASK_BITS + 1];
-
char *s = events;
-
for (i = 0; i < MASK_BITS; ++i, m >>= 1) {
-
if ((m & 1) && (mask_names[i] != '\0'))
-
*s++ = mask_names[i];
-
}
-
*s = '\0';
-
if ( strncmp(args[0],"-", 1) == 0) { //如果argv[1]=='-'时就输出到终端
-
printf(ie->len ? "%s\t%s\t%s\n" : "%s\t%s\n", events, watches[ie->wd], ie->name);
-
fflush(stdout);
-
} else {
-
args[1] = events;
-
args[2] = watches[ie->wd];
-
args[3] = ie->len ? ie->name : NULL;
-
//spawn_and_wait((char **)args);
-
}
-
// we are done if all files got final x event
-
if (ie->mask & 0x8000) {
-
if (--argc <= 0)
-
goto done;
-
inotify_rm_watch(pfd.fd, ie->wd);
-
}
-
}
-
// next event
-
i = sizeof(struct inotify_event) + ie->len;
-
len -= i;
-
ie = (void*)((char*)ie + i);
-
}
-
if (eventbuf != buf)
-
free(buf);
-
}
-
done:
-
return 0;
-
}
2.
使用inotify函数时需要以下几步
a. pfd.fd = inotify_init(); //创建 inotify实例,这儿也可以直接用int fd,但为了后面poll方便就放在了pfd中
b. inotify_add_watch(pfd.fd, path, mask); //添加一个watch
c. pfd.events = POLLIN; //初始化poll
d. poll(&pfd, 1, -1); //调用poll轮询监控watch上有没有事件发生
e. 解析poll的结果 //如果有事件发生就解析事件
14inotify.rar (下载后解压为14inotify.tar.gz)
阅读(2848) | 评论(0) | 转发(0) |