inotify
inotify とは、Linux の ファイルシステム のイベントを監視するための仕組みです。FreeBSD における kevent/kqueue といえます。
読み方
- inotify
- あいのーてぃふぁい
概要
inotify は、Linux において ファイル改竄検知(セキュリティ監視)に役立つ仕組みです。inotify-toolsを利用することで、リアルタイム監視を簡単に実現できます。
inotify は、ファイルシステム を監視するためのシステムコールを提供します。inotify-tools は、inotifyの機能を利用するためのプログラムを提供します。
inotify は、Linuxカーネル 2.6.13 で、組み込まれました。 ファイルシステムのイベント監視は、ファイルマネージャーやセキュリティのツールなどに必要不可欠です。inotify は、1つのファイル記述子を開くことで、1つ以上のファイルやディレクトリのオープン、クローズ、移動・名前の変更、削除、作成、属性の変更などのイベントを指定して監視できます。 イベント監視に select や poll を使用できます。 inotify は、再帰的に監視できません。サブディレクトリの監視には、サブディレクトリを inotify_add_watch() で追加する必要があります。
inotify 以前のdnotify では、ディレクトリごとにファイル記述子を開く必要があり、複数の監視対象が存在する場合、コストが大きく、シグナルハンドリングの扱いにくさも問題でした。また、dnotify では、変更を調べるために stat の情報を持ち続けて、比較しなければなりませんでした。
インストール
inotify の API を C言語から利用する場合には、インストールするものはありません。 inotify-toolsは、インストールが必要です。inotify-toolsを参照してください。
サンプルコード inotify.c
このプログラムは、一度だけ、イベントを拾って、終了します。 一回の read で取得できるイベントだけを取得します。 バッファサイズの上限を超える場合は、うまくハンドリングできないでしょう。
#include <stdio.h> #include <stdlib.h> #include <err.h> #include <errno.h> #include <unistd.h> #include <sys/types.h> #include <sys/inotify.h> #include <linux/limits.h> #define INOTIFY_BUFFER_SIZE ((sizeof(struct inotify_event) + NAME_MAX + 1) * 4096) int Inotify_init (void) { int fd = inotify_init (); if (fd < 0) { perror ("inotify_init"); return (fd); } return (fd); } int Inotify_add_watch (int fd, const char *pathname, uint32_t mask) { int watch_fd = inotify_add_watch (fd, pathname, mask); if (watch_fd == -1) { warn ("can not add inotify:fd=%d, path=%s, mask=%u", fd, pathname, mask); } return (watch_fd); } int read_events (int fd) { int r = -1; char buffer [INOTIFY_BUFFER_SIZE] = { 0 }; struct inotify_event *event_ptr = NULL; r = read (fd, buffer, INOTIFY_BUFFER_SIZE); if (r <= 0) { return (r); } int offset = 0; while (offset < r) { event_ptr = (struct inotify_event *) & buffer [offset]; (void) printf ("name=%s\n", event_ptr->name); offset += sizeof (struct inotify_event) + event_ptr->len; } return r; } int main (int argc, char *argv[]) { int inotify_fd = Inotify_init(); if (inotify_fd < 0) { errx (EXIT_FAILURE, "can not init inotify"); } long mask = IN_ALL_EVENTS; char *path1 = "/tmp"; int wd1 = Inotify_add_watch (inotify_fd, path1, mask); read_events (inotify_fd); exit (EXIT_SUCCESS); }
使い方
$ cc inotify.c
a.out を実行し、 /tmp のファイルを適当にいじります。
$ ./a.out
/tmp/b に追記してみました。
$ echo hoge >> /tmp/b
/tmp/b に追記したとき、3つのイベントが取得されました。
$ ./a.out name=b name=b name=b
カーネルパラメーター
inotify に関連するカーネルのパラメーターがあります。
$ ls /proc/sys/fs/inotify/ max_queued_events max_user_instances max_user_watches
関連項目
- inotify
- inotify-tools
- inotifywait
- inotifywatch
- libinotify
- Tripwire
- Linuxカーネル
- Linux
- ファイルシステム
ツイート