文件和文件夹管理 - 监视文件事件

Linux提供了一个接口inotify来监视文件,比如说监视他们什么时候移动,从哪里被读,写,或删除。

初始化 inotify

#include 
int inotify_init1(int flags);

flag通常为0。
成功返回一个代表初始化实例的fd, 失败返回-1并设置errno。

int  fd;
fd = inotify_init1(0);
if(fd == -1){
      perror("inotity_init1");
      exit(EXIT_FAILURE);
}

监视watch

添加一个新的watch

#include 
int inotify_add_watch(int fd, const char *path, uint32_t mask);

成功返回一个新的watch描述符,失败返回-1并且设置errno。

watch masks

多个inotify event之间是或的关系。

  • IN_ACCESS 文件被读取。
  • IN_MODIFY 文件被写入。
  • IN_ATTRIB
    The file’s metadata (for example, the owner, permissions, or extended attributes)
    was changed.
  • IN_CLOSE_WRITE 文件被写过后关闭。
  • IN_CLOSE_NOWRITE 文件没被写过就关闭了。
  • IN_OPEN 文件被打开了
  • IN_MOVED_FROM 一个文件从监视的文件夹中被移走了。
  • IN_MOVED_TO 一个文件被移入了监视的文件夹中。
  • IN_CREATE 一个文件被创建在监视的文件夹中
  • IN_DELETE 一个文件被删除在监视的文件夹中
  • IN_DELETE_SELF 监视的目标自己删除了。
    IN_MOVE_SELF 监视的目标自身被移走了。
  • 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的所有读或写添加一个watch。 如果/etc 中的任何文件被写入或读取,inotify 将事件发送给文件描述符fd。

inotify Events

#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 */
};

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 
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,并设置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");

你可能感兴趣的:(文件和文件夹管理 - 监视文件事件)