Linux provides an interface, inotify, for monitoring files—for example, to see when they are moved, read from, written to, or deleted.
Linux提供了inotify接口来监控文件——例如,文件的移动、读取、写入或者删除。
1. 初始化inotify
#include
int inotify_init1 (int flags);
The flags parameter is usually 0, but may be a bitwise OR of the following flags:
2. 添加新的监控
#include
int inotify_add_watch (int fd,
const char *path,
uint32_t mask);
On success, the call returns a new watch descriptor. On failure, inotify_add_watch() returns −1 and sets errno to one of the following:
IN_ACCESS
The file was read from.
IN_MODIFY
The file was written to.
IN_ATTRIB
The file’s metadata (for example, the owner, permissions, or extended attributes) was changed.
IN_CLOSE_WRITE
The file was closed and had been open for writing.
IN_CLOSE_NOWRITE
The file was closed and had not been open for writing.
IN_OPEN
The file was opened.
IN_MOVED_FROM
A file was moved away from the watched directory.
IN_MOVED_TO
A file was moved into the watched directory.
IN_CREATE
A file was created in the watched directory.
IN_DELETE
A file was deleted from the watched directory.
IN_DELETE_SELF
The watched object itself was deleted.
IN_MOVE_SELF
The watched object itself was moved.
The following events are also defined, grouping two or more events into a single value:
IN_ALL_EVENTS
All legal events.
IN_CLOSE
All events related to closing (currently, both IN_CLOSE_WRITE and IN_CLOSE_NOWRITE).
IN_MOVE
All move-related events (currently, both IN_MOVED_FROM and IN_MOVED_TO).
3. 读取监控(有变化时)
#include
struct inotify_event {
int wd; /* watch descriptor */
uint32_t mask; /* mask of events */
uint32_t cookie; /* unique cookie */
uint32_t len; /* size of 'name' field */
char name[]; /* nul-terminated name */
};
特别要注意name字段,它是一个zero-length arrays. 后面会有其用法例子。
char buf[BUF_LEN] __attribute__((aligned(4)));
ssize_t len, i = 0;
/* read BUF_LEN bytes' worth of events */
len = read (fd, buf, BUF_LEN);
/* loop over every read event until none remain */
while (i < len) {
struct inotify_event *event =
(struct inotify_event *) &buf[i];
printf ("wd=%d mask=%d cookie=%d len=%d dir=%s\n",
event->wd, event->mask,
event->cookie, event->len,
(event->mask & IN_ISDIR) ? "yes" : "no");
/* if there is a name, print it */
if (event->len)
printf ("name=%s\n", event->name);
/* update the index to the start of the next event */
i += sizeof (struct inotify_event) + event->len;
}
#include
int inotify_rm_watch (int fd, uint32_t wd);
#include
int inotify_rm_watch (int fd, uint32_t wd);
#include
#include
#include
#include
#include
#include
#include
#define INOTIFY_LEN 1024
#define BUFFER_LEN 1024
int main()
{
int fd;
fd = inotify_init1(0);
if (fd == -1)
{
perror("inotify_init1");
exit(EXIT_FAILURE);
}
int wd = inotify_add_watch(fd, "./log.log", IN_CLOSE_WRITE);
if (wd == -1)
{
perror("inotify_add_watch");
exit(EXIT_FAILURE);
}
char buf[INOTIFY_LEN] __attribute__((aligned(4)));
ssize_t len;
off_t curr = 0;
char f_buf[BUFFER_LEN];
//
int f_fd = open("./log.log", O_RDONLY);
if (f_fd == -1)
{
perror("open");
exit(EXIT_FAILURE);
}
curr = lseek(f_fd, 0, SEEK_END);
close(f_fd);
while(1)
{
//wait the inotify event
len = read(fd, buf, INOTIFY_LEN);
//
f_fd = open("./log.log", O_RDONLY);
if (f_fd == -1)
{
perror("open");
exit(EXIT_FAILURE);
}
off_t n_curr = lseek(f_fd, 0, SEEK_END);
if (n_curr > curr)
{
pread(f_fd, f_buf, BUFFER_LEN, curr);
f_buf[n_curr - curr] = '\0';
printf("%s\n", f_buf);
curr = n_curr;
close(f_fd);
}
}
close(fd);
return 0;
}