我想使用inotify来监控目录的内容。在我尝试使用mv命令重命名目录中的文件之前,一切似乎都很好。我按预期得到了IN_MOVED_FROM但是没有IN_MOVED_TO。
以下是我的测试程序。编译:
g++ -Wall -o test test.cpp
启动:
./test dir_to_watch
#include <cstdio>
#include <cstring>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/inotify.h>
int main (int argc, char *argv[])
{
int inotify_fd = inotify_init();
if (inotify_fd < 0)
{
fprintf(stderr, "Unable to init inotify: %m\n");
return 1;
}
int watch_descriptor = inotify_add_watch(inotify_fd,
argv[1],
IN_ALL_EVENTS);
if (watch_descriptor < 0)
{
fprintf(stderr, "Unable to add inotify watch: %m\n");
return 1;
}
union
{
inotify_event event;
char pad[1024];
}
buffer;
struct events
{
int mask;
const char *name;
}
events[] =
{
{IN_ACCESS , "IN_ACCESS "},
{IN_ATTRIB , "IN_ATTRIB "},
{IN_CLOSE_WRITE , "IN_CLOSE_WRITE "},
{IN_CLOSE_NOWRITE , "IN_CLOSE_NOWRITE "},
{IN_CREATE , "IN_CREATE "},
{IN_DELETE , "IN_DELETE "},
{IN_DELETE_SELF , "IN_DELETE_SELF "},
{IN_MODIFY , "IN_MODIFY "},
{IN_MOVE_SELF , "IN_MOVE_SELF "},
{IN_MOVED_FROM , "IN_MOVED_FROM "},
{IN_MOVED_TO , "IN_MOVED_TO "},
{IN_OPEN , "IN_OPEN "},
};
while (read(inotify_fd, &buffer, sizeof buffer) > 0)
{
for (unsigned i = 0; i < sizeof events / sizeof events[0]; i++)
{
if (events[i].mask & buffer.event.mask)
{
if (buffer.event.len)
{
printf("Inotify %s: %s\n", events[i].name, buffer.event.name);
}
else
{
printf("Inotify %s\n", events[i].name);
}
}
}
}
}
答案 0 :(得分:7)
自我解决:事实证明,inotify可以在单个read()调用中返回多个事件。因此,更正后的源代码如下所示:
#include <cstdio>
#include <cstring>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/inotify.h>
int main (int argc, char *argv[])
{
int inotify_fd = inotify_init();
if (inotify_fd < 0)
{
fprintf(stderr, "Unable to init inotify: %m\n");
return 1;
}
int watch_descriptor = inotify_add_watch(inotify_fd,
argv[1],
IN_ALL_EVENTS);
if (watch_descriptor < 0)
{
fprintf(stderr, "Unable to add inotify watch: %m\n");
return 1;
}
struct events
{
int mask;
const char *name;
}
events[] =
{
{IN_ACCESS , "IN_ACCESS "},
{IN_ATTRIB , "IN_ATTRIB "},
{IN_CLOSE_WRITE , "IN_CLOSE_WRITE "},
{IN_CLOSE_NOWRITE , "IN_CLOSE_NOWRITE "},
{IN_CREATE , "IN_CREATE "},
{IN_DELETE , "IN_DELETE "},
{IN_DELETE_SELF , "IN_DELETE_SELF "},
{IN_MODIFY , "IN_MODIFY "},
{IN_MOVE_SELF , "IN_MOVE_SELF "},
{IN_MOVED_FROM , "IN_MOVED_FROM "},
{IN_MOVED_TO , "IN_MOVED_TO "},
{IN_OPEN , "IN_OPEN "},
};
ssize_t rd;
char buffer[1024];
while ((rd = read(inotify_fd, buffer, sizeof buffer)) > 0)
{
for (char *ptr = buffer; ptr != buffer + rd; ptr += sizeof(inotify_event) + reinterpret_cast<inotify_event*>(ptr)->len)
{
inotify_event *event = reinterpret_cast<inotify_event*>(ptr);
for (unsigned i = 0; i < sizeof events / sizeof events[0]; i++)
{
if (events[i].mask & event->mask)
{
if (event->len)
{
printf("Inotify %d %s: %s\n", inotify_fd, events[i].name, event->name);
}
else
{
printf("Inotify %d %s\n", inotify_fd, events[i].name);
}
}
}
}
}
if (rd < 0)
{
fprintf(stderr, "inotify read %d event error: %m\n", inotify_fd);
return 1;
}
}