.\" t
.\" Copyright (C) 2006, 2014 Michael Kerrisk <mtk.manpages@gmail.com>
+.\" Copyright (C) 2014 Heinrich Schuchardt <xypron.glpk@gmx.de>
.\"
.\" %%%LICENSE_START(VERBATIM)
.\" Permission is granted to make and distribute verbatim copies of this
.\" Updated 2013-07-22, Akihiro MOTOKI <amotoki@gmail.com>
.\" Updated 2013-08-21, Akihiro MOTOKI <amotoki@gmail.com>, LDP v3.53
.\"
-.TH INOTIFY 7 2014\-04\-01 Linux "Linux Programmer's Manual"
+.TH INOTIFY 7 2014\-05\-23 Linux "Linux Programmer's Manual"
.SH 名前
inotify \- ファイルシステムイベントを監視する
.SH 説明
(このようなイベントを捉えるにはアプリケーションはファイルシステムをポーリングする必要がある)。 さらに、 \fI/proc\fP, \fI/sys\fP,
\fI/dev/pts\fP といったいくつかの疑似ファイルシステムは inotify で監視することができない。
-inotify API は \fBmmap\fP(2) と \fBmsync\fP(2) により起こったファイルのアクセスと変更を報告しない。
+inotify API は \fBmmap\fP(2), \fBmsync\fP(2), \fBmunmap\fP(2)
+により起こったファイルのアクセスと変更を報告しない。
inotify API では影響が受けるファイルをファイル名で特定する。
しかしながら、アプリケーションが inotify イベントを処理する時点では、
カーネル 2.6.25 より前では、 連続する同一のイベントを一つにまとめることを意図したコード (古い方のイベントがまだ読み込まれていない場合に、
最新の 2 つのイベントを一つにまとめられる可能性がある) が、 最新のイベントが「最も古い」読み込まれていないイベントとまとめられるか
をチェックするようになっていた。
+.SH 例
+以下のプログラムは inotify API の使用例を示したものである。 コマンドライン引き数で渡されたディレクトリに印を付け、 タイプが
+\fBIN_OPEN\fP, \fBIN_CLOSE_NOWRITE\fP \fBIN_CLOSE_WRITE\fP のイベントを待つ。
+.PP
+以下は、 ファイル \fI/home/user/temp/foo\fP を編集し、 ディレクトリ \fI/tmp\fP の一覧表示を行った場合の出力である。
+対象のファイルとディレクトリがオープンされる前に、イベント \fBIN_OPEN\fP が発生している。 対象ファイルがクローズされた後にイベント
+\fBIN_CLOSE_WRITE\fP が発生している。 対象ディレクトリがクローズされた後にイベント \fBIN_CLOSE_NOWRITE\fP
+が発生している。 ユーザーが ENTER キーを押すると、プログラムの実行は終了する。
+.SS 出力例
+.in +4n
+.nf
+$ \fB./a.out /tmp /home/user/temp\fP
+Press enter key to terminate.
+Listening for events.
+IN_OPEN: /home/user/temp/foo [file]
+IN_CLOSE_WRITE: /home/user/temp/foo [file]
+IN_OPEN: /tmp/ [directory]
+IN_CLOSE_NOWRITE: /tmp/ [directory]
+
+Listening for events stopped.
+.fi
+.in
+.SS プログラムソース
+.nf
+#include <errno.h>
+#include <poll.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/inotify.h>
+#include <unistd.h>
+
+/* Read all available inotify events from the file descriptor 'fd'.
+ wd is the table of watch descriptors for the directories in argv.
+ argc is the length of wd and argv.
+ argv is the list of watched directories.
+ Entry 0 of wd and argv is unused. */
+
+static void
+handle_events(int fd, int *wd, int argc, char* argv[])
+{
+ /* Some systems cannot read integer variables if they are not
+ properly aligned. On other systems, incorrect alignment may
+ decrease performance. Hence, the buffer used for reading from
+ the inotify file descriptor should have the same alignment as
+ struct inotify_event. */
+
+ char buf[4096]
+ __attribute__ ((aligned(__alignof__(struct inotify_event))));
+ const struct inotify_event *event;
+ int i;
+ ssize_t len;
+ char *ptr;
+
+ /* Loop while events can be read from inotify file descriptor. */
+
+ for (;;) {
+
+ /* Read some events. */
+
+ len = read(fd, buf, sizeof buf);
+ if (len == \-1 && errno != EAGAIN) {
+ perror("read");
+ exit(EXIT_FAILURE);
+ }
+
+ /* If the nonblocking read() found no events to read, then
+ it returns \-1 with errno set to EAGAIN. In that case,
+ we exit the loop. */
+
+ if (len <= 0)
+ break;
+
+ /* Loop over all events in the buffer */
+
+ for (ptr = buf; ptr < buf + len;
+ ptr += sizeof(struct inotify_event) + event\->len) {
+
+ event = (const struct inotify_event *) ptr;
+
+ /* Print event type */
+
+ if (event\->mask & IN_OPEN)
+ printf("IN_OPEN: ");
+ if (event\->mask & IN_CLOSE_NOWRITE)
+ printf("IN_CLOSE_NOWRITE: ");
+ if (event\->mask & IN_CLOSE_WRITE)
+ printf("IN_CLOSE_WRITE: ");
+
+ /* Print the name of the watched directory */
+
+ for (i = 1; i < argc; ++i) {
+ if (wd[i] == event\->wd) {
+ printf("%s/", argv[i]);
+ break;
+ }
+ }
+
+ /* Print the name of the file */
+
+ if (event\->len)
+ printf("%s", event\->name);
+
+ /* Print type of filesystem object */
+
+ if (event\->mask & IN_ISDIR)
+ printf(" [directory]\en");
+ else
+ printf(" [file]\en");
+ }
+ }
+}
+
+int
+main(int argc, char* argv[])
+{
+ char buf;
+ int fd, i, poll_num;
+ int *wd;
+ nfds_t nfds;
+ struct pollfd fds[2];
+
+ if (argc < 2) {
+ printf("Usage: %s PATH [PATH ...]\en", argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ printf("Press ENTER key to terminate.\en");
+
+ /* Create the file descriptor for accessing the inotify API */
+
+ fd = inotify_init1(IN_NONBLOCK);
+ if (fd == \-1) {
+ perror("inotify_init1");
+ exit(EXIT_FAILURE);
+ }
+
+ /* Allocate memory for watch descriptors */
+
+ wd = calloc(argc, sizeof(int));
+ if (wd == NULL) {
+ perror("calloc");
+ exit(EXIT_FAILURE);
+ }
+
+ /* Mark directories for events
+ \- file was opened
+ \- file was closed */
+
+ for (i = 1; i < argc; i++) {
+ wd[i] = inotify_add_watch(fd, argv[i],
+ IN_OPEN | IN_CLOSE);
+ if (wd[i] == \-1) {
+ fprintf(stderr, "Cannot watch '%s'\en", argv[i]);
+ perror("inotify_add_watch");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ /* Prepare for polling */
+
+ nfds = 2;
+
+ /* Console input */
+
+ fds[0].fd = STDIN_FILENO;
+ fds[0].events = POLLIN;
+
+ /* Inotify input */
+
+ fds[1].fd = fd;
+ fds[1].events = POLLIN;
+
+ /* Wait for events and/or terminal input */
+
+ printf("Listening for events.\en");
+ while (1) {
+ poll_num = poll(fds, nfds, \-1);
+ if (poll_num == \-1) {
+ if (errno == EINTR)
+ continue;
+ perror("poll");
+ exit(EXIT_FAILURE);
+ }
+
+ if (poll_num > 0) {
+
+ if (fds[0].revents & POLLIN) {
+
+ /* Console input is available. Empty stdin and quit */
+
+ while (read(STDIN_FILENO, &buf, 1) > 0 && buf != '\en')
+ continue;
+ break;
+ }
+
+ if (fds[1].revents & POLLIN) {
+
+ /* Inotify events are available */
+
+ handle_events(fd, wd, argc, argv);
+ }
+ }
+ }
+
+ printf("Listening for events stopped.\en");
+
+ /* Close inotify file descriptor */
+
+ close(fd);
+
+ free(wd);
+ exit(EXIT_SUCCESS);
+}
+.fi
.SH 関連項目
\fBinotifywait\fP(1), \fBinotifywatch\fP(1), \fBinotify_add_watch\fP(2),
\fBinotify_init\fP(2), \fBinotify_init1\fP(2), \fBinotify_rm_watch\fP(2), \fBread\fP(2),
-\fBstat\fP(2)
+\fBstat\fP(2), \fBfanotify\fP(7)
Linux カーネルソース内の \fIDocumentation/filesystems/inotify.txt\fP
.SH この文書について
-この man ページは Linux \fIman\-pages\fP プロジェクトのリリース 3.65 の一部
+この man ページは Linux \fIman\-pages\fP プロジェクトのリリース 3.68 の一部
である。プロジェクトの説明とバグ報告に関する情報は
http://www.kernel.org/doc/man\-pages/ に書かれている。