メモ-inotifyファイルモニタリング

5410 ワード

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:
IN_CLOEXEC
Sets close-on-exec on the new file descriptor.
IN_NONBLOCK
Sets O_NONBLOCK on the new file descriptor.
On error, inotify_init1() returns −1 and sets errno to one of the following codes:
EMFILE
The per-user limit on the maximum number of inotify instances has been reached.
ENFILE
The system-wide limit on the maximum number of file descriptors has been
reached.
ENOMEM
There is insufficient memory available to complete the request.
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:
EACCES
Read access to the file specified by path is not permitted. The invoking process must be able to read the file to add a watch to it.
EBADF
The file descriptor fd is not a valid inotify instance.
EFAULT
The pointer path is not valid.
EINVAL
The watch mask, mask, contains no valid events.
ENOMEM
There is insufficient memory available to complete the request.
ENOSPC
The per-user limit on the total number of inotify watches has been reached.
Watch masks
The watch mask is a binary OR of one or more inotify events, which  defines:
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 */
};
特に名前フィールドに注意してください.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
", 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
", event->name); /* update the index to the start of the next event */ i += sizeof (struct inotify_event) + event->len; }

4.モニタの削除
#include 
int inotify_rm_watch (int fd, uint32_t wd);

5.inotifyインスタンスの破棄
#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
", f_buf); curr = n_curr; close(f_fd); } } close(fd); return 0; }