linux文件系统变化通知机制(inotify)

linux文件系统变化通知机制(inotify)

如果我们需要实时的了解一个文件夹或者目录的变化,我们可以使用linux文件系统变化通知机制(inotify),只要有变化,都会收到通知。

inotify是用来监视文件系统事件的机制,在linux 2.6.13内核中引入。

该机制可以用来监视文件和目录,当文件或目录发生变化时,内核会将文件或目录的变化发送给inotify文件描述符,在应用层只需调用read()就可以读取这些事件,非常的方便。更好的是,inotify文件描述符还可以使用select、poll、epoll这些接口来监听,当有事件发生是,inotify文件描述符会可读

1、api介绍


#include 

/* Create and initialize inotify instance.  */
int inotify_init (void);
(1) inotify_init()在内核中创建一个实体,并返回一个文件描述符fd。
(2) 成功的话返回文件描述符,失败返回-1/* Add watch of object NAME to inotify instance FD.  Notify about events specified by MASK.  */
int inotify_add_watch (int __fd, const char *__name, uint32_t __mask);
创建监视器要提供:
(1) inotify实例inotify_init返回的文件描述符:fd。
(2) 监视目标路径:name。
(3) 监视事件列表:mask。
(4) 如果成功,返回监视器描述符wd,否则返回-1/* Remove the watch specified by WD from the inotify instance FD.  */
int inotify_rm_watch (int __fd, int __wd);
用于从监视器列表中删除一个监视器。
(1) fd为inotify_init返回的文件描述符。
(2) wd为inotify_add_watch返回监视器描述符。
(3) 返回值:0 成功,-1 失败。

2、事件结构体

/* Structure describing an inotify event.  */
struct inotify_event
{
  int wd;       /* Watch descriptor.  */
  uint32_t mask;    /* Watch mask.  */
  uint32_t cookie;  /* Cookie to synchronize two events.  */
  uint32_t len;     /* Length (including NULs) of name.  */
  char name;    /* Name.  */
};

(1)wd为监视器描述符。
(2)mask代表当前事件是什么事件,在事件列表可查。
(3len为name的长度。动态变化的,其实就是被监视发生变化的文件夹名或者文件名。
(3)、被监视到的文件夹名称/文件名。

3、事件列表

/* Supported events suitable for MASK parameter of INOTIFY_ADD_WATCH.  */
#define IN_ACCESS    0x00000001 /* File was accessed.  */
#define IN_MODIFY    0x00000002 /* File was modified.  */
#define IN_ATTRIB    0x00000004 /* Metadata changed.  */
#define IN_CLOSE_WRITE   0x00000008 /* Writtable file was closed.  */
#define IN_CLOSE_NOWRITE 0x00000010 /* Unwrittable file closed.  */
#define IN_CLOSE     (IN_CLOSE_WRITE | IN_CLOSE_NOWRITE) /* Close.  */
#define IN_OPEN      0x00000020 /* File was opened.  */
#define IN_MOVED_FROM    0x00000040 /* File was moved from X.  */
#define IN_MOVED_TO      0x00000080 /* File was moved to Y.  */
#define IN_MOVE      (IN_MOVED_FROM | IN_MOVED_TO) /* Moves.  */
#define IN_CREATE    0x00000100 /* Subfile was created.  */
#define IN_DELETE    0x00000200 /* Subfile was deleted.  */
#define IN_DELETE_SELF   0x00000400 /* Self was deleted.  */
#define IN_MOVE_SELF     0x00000800 /* Self was moved.  */

/* Events sent by the kernel.  */
#define IN_UNMOUNT   0x00002000 /* Backing fs was unmounted.  */
#define IN_Q_OVERFLOW    0x00004000 /* Event queued overflowed.  */
#define IN_IGNORED   0x00008000 /* File was ignored.  */

/* Helper events.  */
#define IN_CLOSE     (IN_CLOSE_WRITE | IN_CLOSE_NOWRITE)    /* Close.  */
#define IN_MOVE      (IN_MOVED_FROM | IN_MOVED_TO)      /* Moves.  */

/* Special flags.  */
#define IN_ONLYDIR   0x01000000 /* Only watch the path if it is a
                       directory.  */
#define IN_DONT_FOLLOW   0x02000000 /* Do not follow a sym link.  */
#define IN_MASK_ADD  0x20000000 /* Add to the mask of an already
                       existing watch.  */
#define IN_ISDIR     0x40000000 /* Event occurred against dir.  */
#define IN_ONESHOT   0x80000000 /* Only send event once.  */

/* All events which a program can wait on.  */
#define IN_ALL_EVENTS    (IN_ACCESS | IN_MODIFY | IN_ATTRIB | IN_CLOSE_WRITE  \
              | IN_CLOSE_NOWRITE | IN_OPEN | IN_MOVED_FROM        \
              | IN_MOVED_TO | IN_CREATE | IN_DELETE           \
              | IN_DELETE_SELF | IN_MOVE_SELF)

4、测试程序

//
//  test_inotify.cpp
//  
//
//  Created by jianjian Qi on 9/11/16.
//  Copyright © 2016 tgbtgb. All rights reserved.
//

#include 
#include 
#include 
#include 
#include 

#define EVENT_NUM 12
#define BUFF_SIZE 1024

char *event_str[EVENT_NUM] =
{
  "IN_ACCESS",
  "IN_MODIFY",
  "IN_ATTRIB",
  "IN_CLOSE_WRITE",
  "IN_CLOSE_NOWRITE",
  "IN_OPEN",
  "IN_MOVED_FROM",
  "IN_MOVED_TO",
  "IN_CREATE",
  "IN_DELETE",
  "IN_DELETE_SELF",
  "IN_MOVE_SELF"
};


int main(int argc, char *argv[])
{
  int fd;
  int wd;
  int len;
  int nread;
  char buf[BUFF_SIZE];
  struct inotify_event *event;
  int i;

  if (argc < 2)
  {
    fprintf(stderr, "%s path\n", argv[0]);
    return -1;
  }

  fd = inotify_init();

  if ( fd < 0 )
  {
    fprintf(stderr, "inotify_init failed\n");
    return -1;
  }

  wd = inotify_add_watch(fd, argv[1], IN_ALL_EVENTS);

  if (wd < 0)
  {
    fprintf(stderr, "inotify_add_watch %s failed\n", argv[1]);
    return -1;
  }

  memset(buf, 0, BUFF_SIZE);

  while ( (len = read(fd, buf, sizeof(buf) - 1)) > 0 )
  {
    nread = 0;
    while ( len > 0 )
    {
      event = (struct inotify_event *)&buf[nread];
      for ( i=0; iif ((event->mask >> i) & 1)
        {
          if (event->len > 0)
          {
            fprintf(stdout, "%s --- %s\n", event->name, event_str[i]);
          }
          else
          {
            fprintf(stdout, "%s --- %s\n", " ", event_str[i]);
          }
        }
      }
      nread = nread + sizeof(struct inotify_event) + event->len;
      len   = len - sizeof(struct inotify_event) - event->len;
    }
  }

  return 0;
}

5、编译

#g++ test_inotify.cpp

6、运行

#./a.out ~/Desktop/test/
index0.ts — IN_CREATE
index0.ts — IN_OPEN
index0.ts — IN_MODIFY
index0.ts — IN_MODIFY
index0.ts — IN_MODIFY
index0.ts — IN_MODIFY
index0.ts — IN_MODIFY
index0.ts — IN_MODIFY
index0.ts — IN_MODIFY
index0.ts — IN_MODIFY
index0.ts — IN_MODIFY
index0.ts — IN_MODIFY
index0.ts — IN_MODIFY
index0.ts — IN_MODIFY
index0.ts — IN_MODIFY
index0.ts — IN_MODIFY
index0.ts — IN_MODIFY
index0.ts — IN_MODIFY
index0.ts — IN_MODIFY
index0.ts — IN_MODIFY
index0.ts — IN_MODIFY
index0.ts — IN_MODIFY
index0.ts — IN_MODIFY
index0.ts — IN_MODIFY
index0.ts — IN_MODIFY
index0.ts — IN_MODIFY
index0.ts — IN_MODIFY
index0.ts — IN_MODIFY
index0.ts — IN_MODIFY
index0.ts — IN_MODIFY
index0.ts — IN_MODIFY
index0.ts — IN_MODIFY
index0.ts — IN_MODIFY
index0.ts — IN_MODIFY
index0.ts — IN_MODIFY
index0.ts — IN_MODIFY
index0.ts — IN_MODIFY
index0.ts — IN_CLOSE_WRITE
index1.ts — IN_CREATE
index1.ts — IN_OPEN
index.m3u8.tmp — IN_CREATE
index.m3u8.tmp — IN_OPEN
index.m3u8.tmp — IN_MODIFY
index.m3u8.tmp — IN_CLOSE_WRITE
index.m3u8.tmp — IN_MOVED_FROM
index.m3u8 — IN_MOVED_TO

参考网址:http://linux.die.net/man/7/inotify

你可能感兴趣的:(c/c++,linux)