Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2112585
  • 博文数量: 438
  • 博客积分: 3871
  • 博客等级: 中校
  • 技术积分: 6075
  • 用 户 组: 普通用户
  • 注册时间: 2011-09-10 00:11
个人简介

邮箱: wangcong02345@163.com

文章分类

全部博文(438)

文章存档

2017年(15)

2016年(119)

2015年(91)

2014年(62)

2013年(56)

2012年(79)

2011年(16)

分类: LINUX

2015-08-05 15:00:40

1. inotifyd
这次看的是busybox源码下的./miscutils/inotifyd.c
  1. 使用说明:
  2. inotifyd PROG FILE1[:MASK]...
  3. If PROG is -, events are sent to stdout.
  4. Events:
  5.     a    File is accessed
  6.     c    File is modified
  7.     e    Metadata changed
  8.     w    Writable file is closed
  9.     0    Unwritable file is closed
  10.     r    File is opened
  11.     D    File is deleted
  12.     M    File is moved
  13.     u    Backing fs is unmounted
  14.     o    Event queue overflowed
  15.     x    File can't be watched anymore
  16. If watching a directory:
  17.     m    Subfile is moved into dir
  18.     y    Subfile is moved out of dir
  19.     n    Subfile is created
  20.     d    Subfile is deleted

  21. 使用方法:
  22. ./_install/busybox inotifyd - /tmp/test/1.c:r

  23. a. 监测文件
  24. cong@msi:/tmp/test$ cat 1.c //-->terminal1
  25. 就会打印:
  26. cong@msi:/work/busybox$ ./_install/busybox inotifyd - /tmp/test/1.c:r //-->terminal2先运行
  27. r /tmp/test/1.c

  28. b. 监测目录
  29. cong@msi:/tmp/test$ touch 4.c //-->terminal1
  30. cong@msi:/work/busybox$ ./_install/busybox inotifyd - /tmp/test/:n //-->terminal2 先运行
  31. n    /tmp/test/    4.c

  32. cong@msi:/tmp/test$ rm 4.c //-->terminal1
  33. cong@msi:/work/busybox$ ./_install/busybox inotifyd - /tmp/test/:d //-->terminal2 先运行
  34. d    /tmp/test/    4.c
2. 源码
我把./miscutils/inotifyd.c改成了一个独立的小程序

  1. cong@msi:/work/test/busytest/14inotify$ cat inotify.c
  2. #include "./utils.h"
  3. #include <sys/inotify.h>
  4. #include <poll.h>
  5. #include <sys/ioctl.h> //FIONREAD

  6. //static const char mask_names[] ALIGN1 =
  7. static const char mask_names[] =
  8.     "a"    // 0x00000001    File was accessed
  9.     "c"    // 0x00000002    File was modified
  10.     "e"    // 0x00000004    Metadata changed
  11.     "w"    // 0x00000008    Writable file was closed
  12.     "0"    // 0x00000010    Unwritable file closed
  13.     "r"    // 0x00000020    File was opened
  14.     "m"    // 0x00000040    File was moved from X
  15.     "y"    // 0x00000080    File was moved to Y
  16.     "n"    // 0x00000100    Subfile was created
  17.     "d"    // 0x00000200    Subfile was deleted
  18.     "D"    // 0x00000400    Self was deleted
  19.     "M"    // 0x00000800    Self was moved
  20.     "\0"    // 0x00001000 (unused)                   //-->\0之后就没有用了,mask=0x0fff也是12位的
  21.     // Kernel events, always reported:
  22.     "u"    // 0x00002000 Backing fs was unmounted
  23.     "o"    // 0x00004000 Event queued overflowed
  24.     "x"    // 0x00008000 File is no longer watched (usually deleted)
  25. ;
  26. enum {
  27.     MASK_BITS = sizeof(mask_names) - 1
  28. };

  29. int main(int argc, char **argv)
  30. {
  31.     int n;
  32.     unsigned mask;
  33.     struct pollfd pfd;
  34.     char **watches; // names of files being watched
  35.     const char *args[5];
  36.     char eventbuf[1024];

  37.     //argv[1]结果显示的地方,-代表输出到stdout; argv[2]是要监测的文件或目录
  38.     if (!argv[1] || !argv[2])
  39.     {
  40.         printf("usage: inotify - [FILE]:[MASK]\n");
  41.         return -1;
  42.     }

  43.     argv++;

  44.     watches = argv;
  45.     args[0] = *argv;
  46.     args[4] = NULL;
  47.     argc -= 2; // number of files we watch

  48.     //a. 创建 inotify实例
  49.     pfd.fd = inotify_init();
  50.     if (pfd.fd < 0)
  51.         dbmsg("no kernel support");

  52.     //这个地方很经典,要详细分析
  53.     while (*++argv) {                       //假设参数="/tmp/test/1.c:r"
  54.         char *path = *argv;                 //此处path="/tmp/test/1.c:r"
  55.         char *masks = strchr(path, ':');    //查找:此时masks=:r
  56.         mask = 0x0fff;
  57.         if (masks) {
  58.             *masks = '\0';                 //masks=\0r,那么path="/tmp/test/1.c"
  59.             mask = 0;
  60.             while (*++masks) {             //因为是++masks,所以*masks='r'
  61.                 const char *found;
  62.                 found = memchr(mask_names, *masks, MASK_BITS);  //从mask_names[] ="acew0rmyndDm\0uox";中找到r的地址
  63.                 if (found)
  64.                     mask |= (1 << (found - mask_names));   //found-mask_names就是r在mask_names中的第几项,然后移位就是mask
  65.             }
  66.         }
  67.         //b.添加一个watch
  68.         n = inotify_add_watch(pfd.fd, path, mask);
  69.         if (n < 0)
  70.             dbmsg("add watch (%s) failed", path);
  71.     }
  72.     //c.poll结构体初始化
  73.     pfd.events = POLLIN;
  74.     while (1) {
  75.         int len;
  76.         void *buf;
  77.         struct inotify_event *ie;
  78.  again:
  79.         n = poll(&pfd, 1, -1);                 //d.调用poll轮询监控watch上有没有事件发生
  80.         if (n < 0 && errno == EINTR)           //被信号中断,返回继续等待
  81.             goto again;
  82.         if (n <= 0)                            //真正有error了,就break退出
  83.             break;
  84.         ioctl(pfd.fd, FIONREAD, &len);         //调用ioctl 命令的FIONREAD 来得到当前队列的长度
  85.         ie = buf = (len <= sizeof(eventbuf)) ? eventbuf : malloc(len);
  86.         len = read(pfd.fd, buf, len);
  87.         //e.下面就处理buffer
  88.         while (len > 0) {
  89.             int i;
  90.             // cache relevant events mask
  91.             unsigned m = ie->mask & ((1 << MASK_BITS) - 1);
  92.             if (m) {
  93.                 char events[MASK_BITS + 1];
  94.                 char *s = events;
  95.                 for (i = 0; i < MASK_BITS; ++i, m >>= 1) {
  96.                     if ((m & 1) && (mask_names[i] != '\0'))
  97.                         *s++ = mask_names[i];
  98.                 }
  99.                 *s = '\0';
  100.                 if ( strncmp(args[0],"-", 1) == 0) {   //如果argv[1]=='-'时就输出到终端
  101.                     printf(ie->len ? "%s\t%s\t%s\n" : "%s\t%s\n", events, watches[ie->wd], ie->name);
  102.                     fflush(stdout);
  103.                 } else {
  104.                     args[1] = events;
  105.                     args[2] = watches[ie->wd];
  106.                     args[3] = ie->len ? ie->name : NULL;
  107.                     //spawn_and_wait((char **)args);
  108.                 }
  109.                 // we are done if all files got final x event
  110.                 if (ie->mask & 0x8000) {
  111.                     if (--argc <= 0)
  112.                         goto done;
  113.                     inotify_rm_watch(pfd.fd, ie->wd);
  114.                 }
  115.             }
  116.             // next event
  117.             i = sizeof(struct inotify_event) + ie->len;
  118.             len -= i;
  119.             ie = (void*)((char*)ie + i);
  120.         }
  121.         if (eventbuf != buf)
  122.             free(buf);
  123.     }
  124.  done:
  125.     return 0;
  126. }
2.
使用inotify函数时需要以下几步
a. pfd.fd = inotify_init();                         //创建 inotify实例,这儿也可以直接用int fd,但为了后面poll方便就放在了pfd中
b. inotify_add_watch(pfd.fd, path, mask); //添加一个watch
c. pfd.events = POLLIN;                         //初始化poll
d. poll(&pfd, 1, -1);                               //调用poll轮询监控watch上有没有事件发生
e. 解析poll的结果                                    //如果有事件发生就解析事件
14inotify.rar (下载后解压为14inotify.tar.gz)

阅读(2721) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~