Linux提供了一個接口inotify來監(jiān)視文件溶浴,比如說監(jiān)視他們什么時候移動案铺,從哪里被讀,寫鹦蠕,或刪除冒签。
初始化 inotify
#include <sys/inotify.h>
int inotify_init1(int flags);
flag通常為0。
成功返回一個代表初始化實例的fd, 失敗返回-1并設(shè)置errno钟病。
int fd;
fd = inotify_init1(0);
if(fd == -1){
perror("inotity_init1")萧恕;
exit(EXIT_FAILURE);
}
監(jiān)視watch
添加一個新的watch
#include <sys/inotify.h>
int inotify_add_watch(int fd, const char *path, uint32_t mask);
成功返回一個新的watch描述符,失敗返回-1并且設(shè)置errno档悠。
watch masks
多個inotify event之間是或的關(guān)系廊鸥。
- IN_ACCESS 文件被讀取望浩。
- IN_MODIFY 文件被寫入辖所。
- IN_ATTRIB
The file’s metadata (for example, the owner, permissions, or extended attributes)
was changed. - IN_CLOSE_WRITE 文件被寫過后關(guān)閉。
- IN_CLOSE_NOWRITE 文件沒被寫過就關(guān)閉了磨德。
- IN_OPEN 文件被打開了
- IN_MOVED_FROM 一個文件從監(jiān)視的文件夾中被移走了缘回。
- IN_MOVED_TO 一個文件被移入了監(jiān)視的文件夾中。
- IN_CREATE 一個文件被創(chuàng)建在監(jiān)視的文件夾中
- IN_DELETE 一個文件被刪除在監(jiān)視的文件夾中
- IN_DELETE_SELF 監(jiān)視的目標(biāo)自己刪除了典挑。
IN_MOVE_SELF 監(jiān)視的目標(biāo)自身被移走了酥宴。 - IN_ALL_EVENTS All legal events.
- IN_CLOSE All events related to closing (currently, both IN_CLOSE_WRITE and IN_CLOSE_NOW
RITE). - IN_MOVE All move-related events (currently, both IN_MOVED_FROM and IN_MOVED_TO).
int wd;
wd = inotify_add_watch (fd, "/etc", IN_ACCESS | IN_MODIFY);
if (wd == ?1) {
perror ("inotify_add_watch");
exit (EXIT_FAILURE);
}
示例為/etc的所有讀或?qū)懱砑右粋€watch。 如果/etc 中的任何文件被寫入或讀取您觉,inotify 將事件發(fā)送給文件描述符fd拙寡。
inotify Events
#include <sys/inotify.h>
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 */
};
Reading inotify events
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);
Advanced inotify events
In addition to the standard events, inotify can generate other events:
- IN_IGNORED
The watch represented by wd has been removed. This can occur because the user manually removed the watch or because the watched object no longer exists. We will discuss this event in a subsequent section. - IN_ISDIR
The affected object is a directory. (If not set, the affected object is a file.) - IN_Q_OVERFLOW
The inotify queue overflowed. The kernel limits the size of the event queue to prevent unbounded consumption of kernel memory. Once the number of pending events reaches one less than the maximum, the kernel generates this event and appends it to the tail of the queue. No further events are generated until the queue
is read from, reducing its size below the limit. - IN_UNMOUNT
The device backing the watched object was unmounted. Thus, the object is no longer available; the kernel will remove the watch and generate the IN_IGNORED
event.
Any watch can generate these events; the user need not set them explicitly.
if (event->mask & IN_ACCESS)
printf ("The file was read from!\n");
if (event->mask & IN_UNMOUNTED)
printf ("The file's backing device was unmounted!\n);
if (event->mask & IN_ISDIR)
printf ("The file is a directory!\n");
Advanced WatchOptions
- IN_DONT_FOLLOW
If this value is set, and if the target of path or any of its components is a symbolic link, the link is not followed and inotify_add_watch() fails. - IN_MASK_ADD
Normally, if you call inotify_add_watch() on a file on which you have an existing watch, the watch mask is updated to reflect the newly provided mask. If this flag is
set in mask, the provided events are added to the existing mask. - IN_ONESHOT
If this value is set, the kernel automatically removes the watch after generating the first event against the given object. The watch is, in effect, “one shot.” - IN_ONLYDIR
If this value is set, the watch is added only if the object provided is a directory. If path represents a file, not a directory, inotify_add_watch() fails.
int wd;
/*
* Watch '/etc/init.d' to see if it moves, but only if it is a
* directory and no part of its path is a symbolic link.
*/
wd = inotify_add_watch (fd,"/etc/init.d",
IN_MOVE_SELF |
IN_ONLYDIR |
IN_DONT_FOLLOW);
if (wd == ?1)
perror ("inotify_add_watch");
Removing an inotify Watch
#include <inotify.h>
int inotify_rm_watch (int fd, uint32_t wd);
int ret;
ret = inotify_rm_watch (fd, wd);
if (ret)
perror ("inotify_rm_watch");
成功返回0,失敗返回-1琳水,并設(shè)置errno肆糕。
Obtaining the Size of the Event Queue
unsigned int queue_len;
int ret;
ret = ioctl (fd, FIONREAD, &queue_len);
if (ret < 0)
perror ("ioctl");
else
printf ("%u bytes pending in queue\n", queue_len);
Destroying an inotify Instance
int ret;
/* 'fd' was obtained via inotify_init() */
ret = close (fd);
if (fd == ?1)
perror ("close");