Chinaunix首页 | 论坛 | 博客
  • 博客访问: 109337
  • 博文数量: 27
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 360
  • 用 户 组: 普通用户
  • 注册时间: 2013-08-07 00:14
文章分类

全部博文(27)

文章存档

2015年(1)

2014年(20)

2013年(6)

我的朋友

分类: C/C++

2013-11-29 22:42:42

man 7 inotify 有下面这样一段描述:

       Since Linux 2.6.25, signal-driven I/O notification is available for inotify file descriptors; see the discussion of  F_SETFL  (for  setting  the
       O_ASYNC flag), F_SETOWN, and F_SETSIG in fcntl(2).  The siginfo_t structure (described in sigaction(2)) that is passed to the signal handler has
       the following fields set: si_fd is set to the inotify file descriptor number; si_signo is set to the signal number; si_code is set  to  POLL_IN;
       and POLLIN is set in si_band.

我们使用下面的程序来验证一下:

点击(此处)折叠或打开

  1. #define _GNU_SOURCE
  2. #include <string.h>
  3. #include <unistd.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <aio.h>
  7. #include <errno.h>
  8. #include <sys/inotify.h>
  9. #include <signal.h>
  10. #include <fcntl.h>
  11. #include <sys/epoll.h>


  12. #define errmsg_exit do {\
  13.                         fprintf(stderr, "%s: -------- err msg:%s\n", __FUNCTION__, strerror(errno));\
  14.                         exit(-1);\
  15.                     }while(0);

  16. #define ENTER do {\
  17.                     fprintf(stderr, "######### enter %s \n", __FUNCTION__);\
  18.                 }while(0);

  19. #define LEAVE do {\
  20.                     fprintf(stderr, "######### leave %s \n", __FUNCTION__);\
  21.                 }while(0);
  22. void sig_io(int signo, siginfo_t *siginfo, void *context)
  23. {
  24.     ENTER;

  25.     LEAVE;
  26. }
  27. struct inotify_event* event;
  28. int buf_len;
  29. void do_read(int fd)
  30. {
  31.     memset(event, 0, buf_len);
  32.     while ( read(fd, event, buf_len) != -1 )
  33.     {
  34.         {
  35.             if( event->mask & IN_OPEN)
  36.                 fprintf(stdout, "有一个文件在目录下被打开, 文件名为:%s.\n", event->name);

  37.             if( event->mask & IN_CREATE)
  38.                 fprintf(stdout, "有一个文件在目录下创建, 文件名为:%s.\n", event->name);
  39.     
  40.             if( event->mask & IN_DELETE)
  41.                 fprintf(stdout, "有一个文件在目录下删除, 文件名为:%s.\n", event->name);
  42.         
  43.             if( event->mask & IN_MOVE_SELF)
  44.                 fprintf(stdout, "目录本身被删除了...\n");

  45.             if( event->mask & IN_MOVED_FROM)
  46.                 fprintf(stdout, "有一个文件移出目录, 文件名为:%s.\n", event->name);
  47.             
  48.             if( event->mask & IN_MOVED_TO)
  49.                 fprintf(stdout, "有一个文件移进目录, 文件名为:%s.\n", event->name);
  50.             
  51.             if( event->mask & IN_CLOSE_WRITE)
  52.                 fprintf(stderr, "有一个文件已经关闭写操作, 文件名为:%s.\n", event->name);
  53.         
  54.         }
  55.     memset(event, 0, buf_len);
  56.     }

  57. }

  58. int main(int argc, char *argv[])
  59. {
  60.     // 创建监控对象
  61.     int fd_inotify = inotify_init1(IN_NONBLOCK);
  62.     if (fd_inotify == -1)
  63.     {
  64.         fprintf(stderr, "不能创建监控对象,系统提示错误信息为:%s.\n", strerror(errno));
  65.         exit(EXIT_FAILURE);
  66.     }
  67.     const char *dir_path = argv[1];    

  68.     // 把由命令行专递进来的目录加入到监控对象的监控列表中
  69.     int inotify_a_fd = inotify_add_watch(fd_inotify, dir_path, IN_OPEN | IN_DELETE | IN_DELETE_SELF | IN_CREATE | IN_CLOSE_WRITE | IN_MOVED_FROM | IN_MOVED_TO);
  70.     if (inotify_a_fd == -1)
  71.     {
  72.         fprintf(stderr, "不能向监控对象的监控列表上添加对象,系统提示错误信息为:%s.\n", strerror(errno));
  73.         exit(EXIT_FAILURE);
  74.     }

  75.     int old_errno = errno;
  76.     int file_name_max;
  77.     if ( (file_name_max = pathconf(dir_path, _PC_NAME_MAX)) == -1 )
  78.     {
  79.         if (errno == old_errno)
  80.         {
  81.             file_name_max = 1024; // 无法从系统得到当前目录所支持的最大文件名,所有只好猜测最大路径名为1024个字节
  82.         }
  83.         else
  84.         {
  85.             fprintf(stderr, "不能从系统上读取目录 %s 下的最大文件名长度,系统提示错误信息为:%s.\n", dir_path, strerror(errno));
  86.             exit(EXIT_FAILURE);
  87.         }
  88.     }


  89.     buf_len = sizeof(*event) + file_name_max + 1;
  90.     event = malloc(buf_len);
  91.     memset(event, 0, buf_len);

  92.     //int fd_n = epoll_create(1);
  93.     //if (fd_n == -1)
  94.     //{
  95.     //    fprintf(stderr, "main: can not allocate an notify instance, err msg: %s\n", strerror(errno));
  96.     //}
  97.     //
  98.     //struct epoll_event en;
  99.     //en.data.fd = fd_inotify;
  100.     //en.events = EPOLLIN | EPOLLET;
  101.     //if (epoll_ctl(fd_n, EPOLL_CTL_ADD, fd_inotify, &en) != 0)
  102.     //{
  103.     //    fprintf(stderr, "main: epoll_ctl failed, err msg: %s\n", strerror(errno));
  104.     //    exit(EXIT_FAILURE);
  105.     //}

  106.     //fprintf(stdout, "************* Get ready to notify .....\n");
  107.     //struct epoll_event rt_en;
  108.     //int n_en;
  109.     //while ((n_en = epoll_wait(fd_n, &rt_en, 1, -1)) != -1)
  110.     //{
  111.     //    if (rt_en.data.fd == fd_inotify)
  112.     //    {
  113.     //        do_read(fd_inotify);
  114.     //    }
  115.     //}

  116.     
  117.     struct sigaction act;
  118.     act.sa_sigaction = sig_io;
  119.     act.sa_flags = SA_SIGINFO;
  120.     sigemptyset(&act.sa_mask);

  121.     if (sigaction(SIGIO, &act, NULL) != 0)
  122.     {
  123.         errmsg_exit;
  124.     }

  125.     if (fcntl(fd_inotify, F_SETFL, O_ASYNC) != 0)
  126.     {
  127.         errmsg_exit;
  128.     }
  129.     
  130.     if (fcntl(fd_inotify, F_SETSIG, SIGIO) != 0)
  131.     {
  132.         errmsg_exit;
  133.     }
  134.     if (fcntl(fd_inotify, F_SETOWN, getpid()) != 0)
  135.     {
  136.         errmsg_exit;
  137.     }


  138.     while (1);
  139.     exit(EXIT_SUCCESS);
  140. }

   当被监控对象上有相应的动作发生, SIGIO 信号被没有发出。具体原因先看看 open 函数的另一段描述:

       O_ASYNC
              Enable signal-driven I/O: generate a signal (SIGIO by default, but this can be changed via fcntl(2)) when input or output becomes  possi-
              ble  on  this  file descriptor.  This feature is only available for terminals, pseudo-terminals, sockets, and (since Linux 2.6) pipes and
              FIFOs.  See fcntl(2) for further details.
 
   红色部分能说明原因。哎, Linux 下的 man 也有错误的时候,所以当我们在查阅文档时,最好自己动手测试。

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