我从互联网上的many examples获取了有关如何使用inotify的代码。
然后我尝试了以下实验:
1)运行下面的观察者
2)在一个单独的shell中,cd进入'/mypath'
创建一些文件到你正在观看的文件夹。例如,'date > output.txt'
一次或多次
3)您将看到来自观察者的通知
4)键入'ls /mypath'
(或甚至'watch -n 1 /mypath'
)
5)在/ mypath中尝试'date > output.txt'
。您将不再看到来自观察者的通知。或者至少,这是我用Ubuntu 12/13测试时发生的事情。
有关如何修复它的任何想法?
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/inotify.h>
#include <limits.h>
#include <unistd.h>
#define MAX_EVENTS 1024 /*Max. number of events to process at one go*/
#define LEN_NAME 16 /*Assuming that the length of the filename won't exceed 16 bytes*/
#define EVENT_SIZE ( sizeof (struct inotify_event) ) /*size of one event*/
#define BUF_LEN ( MAX_EVENTS * ( EVENT_SIZE + LEN_NAME )) /*buffer to store the data of events*/
int main()
{
int length, i = 0, wd;
int fd;
char buffer[BUF_LEN];
/* Initialize Inotify*/
fd = inotify_init();
if ( fd < 0 ) {
perror( "Couldn't initialize inotify");
}
/* add watch to starting directory */
wd = inotify_add_watch(fd, "/mypath", IN_CLOSE_WRITE | IN_CLOSE_NOWRITE);
if (wd == -1)
{
printf("Couldn't add watch to %s\n","/mypath");
}
else
{
printf("Watching:: %s\n","/mypath");
}
/* do it forever*/
while(1)
{
i = 0;
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_CLOSE_WRITE) {
if (event->mask & IN_ISDIR)
printf( "The directory %s was Created.\n", event->name );
else
printf( "The file %s was closed (write) with WD %d\n", event->name, event->wd );
}
if ( event->mask & IN_CLOSE_NOWRITE) {
if (event->mask & IN_ISDIR)
printf( "The directory %s was Created.\n", event->name );
else
printf( "The file %s was closed (nowrite) with WD %d\n", event->name, event->wd );
}
i += EVENT_SIZE + event->len;
}
}
}
/* Clean up*/
inotify_rm_watch( fd, wd );
close( fd );
return 0;
}
答案 0 :(得分:2)
您不应将i += EVENT_SIZE + event->len;
放在if ( event->len )
块中。如果一个事件的名称为零长度,那么指针仍应增加EVENT_SIZE
(如果你将该语句放在该块之外,将会发生这种情况)。我想你可能会在你的inotify程序中看到一个无限循环,由第一个碰巧有零长度名称的事件开始。 (这正是ls
所发生的情况:正在打开目录,而不是其文件,因此name
字段中没有任何内容。)
答案 1 :(得分:1)
你进入一个永无止境的循环,因为i
时你不会改变event->len == 0
加上这个:
else
i += EVENT_SIZE ;
以防if ( event->len == 0 )
答案 2 :(得分:1)
事实证明,当程序停止工作时,它会占用所有CPU。我做了一些改动,现在似乎工作了。以下是详细信息:
声明BUF_LEN以处理16个事件(您可以增加该值):
#define BUF_LEN (16 * (sizeof(struct inotify_event) + NAME_MAX + 1))
将处理事件的while (i < length)
循环更改为以下循环:
for ( p = buffer; p < buffer + length; ) {
struct inotify_event *event = ( struct inotify_event * ) p;
p += sizeof(struct inotify_event) + event->len;
if ( event->len ) {
/* SNIP */
}
}
p
变量应声明为char *
,您可以删除不再使用的i
。