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

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

初始化 inotify

#include <sys/inotify.h>
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 <sys/inotify.h>
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 <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,并设置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");
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • rljs by sennchi Timeline of History Part One The Cognitiv...
    sennchi阅读 12,162评论 0 10
  • The Inner Game of Tennis W Timothy Gallwey Jonathan Cape ...
    网事_79a3阅读 14,269评论 3 20
  • 日常应用中,常常会遇到以下场景,监控文件夹A,若文件夹中的B文件发生变化,则执行C命令。Linux下可以通过ino...
    SkTj阅读 6,380评论 0 0
  • 在我们人生的旅途上,我们一直面临选择。我们每一次选择,都竭尽全力希望自己的选择是正确的。 事与愿违,我们面临的选择...
    心云书阅读 2,649评论 0 3
  • 【大伟荐语】人必须争气和强大,才不会被欺负;也必须谦逊和慈悲,才不会欺负别人。 ——张小娴 ​​​​ 遐思...
    求索大伟阅读 775评论 0 0