详解Linux 2.6内核新文件系统变化机制( 四 )


};
struct wd_name {
int wd;
char * name;
};
#define WD_NUM 3
struct wd_name wd_array[WD_NUM];
char * event_array[] = {
"File was accessed",
"File was modified",
"File attributes were changed",
"writtable file closed",
"Unwrittable file closed",
"File was opened",
"File was moved from X",
"File was moved to Y",
"Subfile was created",
"Subfile was deleted",
"Self was deleted",
"Self was moved",
"",
"Backing fs was unmounted",
"Event queued overflowed",
"File was ignored"
};
#define EVENT_NUM 16
#define MAX_BUF_SIZE 1024

int main(void)
{
int fd;
int wd;
char buffer[1024];
char * offset = NULL;
struct inotify_event * event;
int len, tmp_len;
char strbuf[16];
int i = 0;

fd = inotify_init();
if (fd < 0) {
printf("Fail to initialize inotify.n");
exit(-1);
}
for (i=0; i wd_array[i].name = monitored_files[i];
wd = inotify_add_watch(fd, wd_array[i].name, IN_ALL_EVENTS);
if (wd < 0) {
printf("Can"t add watch for %s.n", wd_array[i].name);
exit(-1);
}
wd_array[i].wd = wd;
}
while(len = read(fd, buffer, MAX_BUF_SIZE)) {
offset = buffer;
printf("Some event happens, len = %d.n", len);
event = (struct inotify_event *)buffer;
while (((char *)event - buffer) < len) {
if (event->mask & IN_ISDIR) {
memcpy(strbuf, "Direcotory", 11);
}
else {
memcpy(strbuf, "File", 5);
}
printf("Object type: %sn", strbuf);
for (i=0; i if (event->wd != wd_array[i].wd) continue;
printf("Object name: %sn", wd_array[i].name);
break;
}
printf("Event mask: Xn", event->mask);
for (i=0; i if (event_array[i][0] == "") continue;
if (event->mask & (1< printf("Event: %sn", event_array[i]);
}
}
tmp_len = sizeof(struct inotify_event)event->len;
event = (struct inotify_event *)(offsettmp_len)
offset= tmp_len;
}
}
}

该程序将监视发生在当前目录下的文件 tmp_file 与当前目录下的目录 tmp_dir 上的所有文件系统事件,同时它也将监视发生在文件 /mnt/sda3/windows_file 上的文件系统事件,注意,/mnt/sda3 是 SATA 硬盘分区 3 的挂接点 。
细心的读者可能注意到,该程序首部使用 _syscallN 来声明 inotify 系统调用,原因是这些系统调用是在最新的稳定内核 2.6.13 中引入的,glibc 并没有实现这些系统调用的库函数版本,因此,为了能在程序中使用这些系统调用,必须通过 _syscallN 来声明这些新的系统,其中的 N 为要声明的系统调用实际的参数数 。还有需要注意的地方是系统的头文件必须与被启动的内核匹配,为了让上面的程序能够成功编译,必须让 2.6.13 的内核头文件(包括 include/linux/*, include/asm/* 和 include/asm-generic/*)在头文件搜索路径内,并且是第一优先搜索的头文件路径,因为 _syscallN 需要用到这些头文件中的 linux/unistd.h 和 asm/unistd.h,它们包含了 inotify 的三个系统调用的系统调用号 __NR_inotify_init、__NR_inotify_add_watch 和 __NR_inotify_rm_watch 。
因此,要想成功编译此程序,只要把用户编译好的内核的头文件拷贝到该程序所在的路径,并使用如下命令编译即可:

$gcc -o inotify_example; -I. inotify_example.c

注意:当前目录下应当包含 linux、asm 和 asm-generic 三个已编译好的 2.6.13 内核的有文件目录,asm 是一个链接,因此拷贝 asm 头文件的时候需要拷贝 asm 与 asm-ARCH(对于 x86 平台应当是 asm-i386) 。然后,为了运行该程序,需要在当前目录下创建文件 tmp_file 和目录 tmp_dir,对于/mnt/sda3/windows_file 文件,用户需要依自己的实际情况而定,可能是/mnt/dosc/windows_file,即 /mnt/dosc 是一个 FAT32 的 windows 硬盘,因此用户在编译该程序时需要根据自己的实际情况来修改 /mnt/sda3 。Windows_file 是在被 mount 硬盘上创建的一个文件,为了运行该程序,它必须被创建 。

推荐阅读