【问题标题】:inotify with signal implementation - linux, c++带有信号实现的 inotify - linux, c++
【发布时间】:2010-11-02 13:54:11
【问题描述】:

我想在我的 linux c++ 应用程序中实现,用信号进行 inotify。我希望我的应用程序在文件发生更改时检索事件。 (没有轮询)

来自 inotify 手册页:

从 Linux 2.6.25 开始,信号驱动的 I/O 通知可用于 inotify 文件描述符;请参阅 F_SETFL 的讨论(用于设置 O_ASYNC fcntl(2) 中的标志)、F_SETOWN 和 F_SETSIG。 siginfo_t 结构(描述 在传递给信号处理程序的 sigaction(2)) 中具有以下字段 set:si_fd设置为inotify文件描述符号; si_signo 设置为 信号编号; si_code 设置为 POLL_IN;并且 POLLIN 设置在 si_band 中。

我不明白怎么做,你能给我发一份样品吗?

10!

【问题讨论】:

    标签: c++ linux signals inotify


    【解决方案1】:

    您真的需要信号方法吗?最常见的使用 inotify 的方法是 selectpoll 文件描述符。如果你有一个长时间运行的应用程序,你可能会调用这些函数,你需要做的就是将额外的 inotify 文件描述符传递给它们。

    【讨论】:

      【解决方案2】:

      这是 TLPI 代码的混合。 listing 19-1 的 inotify API 和 listing 63-3 的信号驱动 I/O。

      #include <limits.h>
      #include <fcntl.h>
      #include <signal.h>
      #include <stdio.h>
      #include <stdlib.h>
      #include <string.h>
      #include <sys/inotify.h>
      #include <unistd.h>
      
      
      static int inotifyFd;
      
      
      static void displayInotifyEvent(struct inotify_event *i)
      {
          printf("    wd =%2d; ", i->wd);
          if (i->cookie > 0)
              printf("cookie =%4d; ", i->cookie);
      
          printf("mask = ");
          if (i->mask & IN_ACCESS)        printf("IN_ACCESS ");
          if (i->mask & IN_ATTRIB)        printf("IN_ATTRIB ");
          if (i->mask & IN_CLOSE_NOWRITE) printf("IN_CLOSE_NOWRITE ");
          if (i->mask & IN_CLOSE_WRITE)   printf("IN_CLOSE_WRITE ");
          if (i->mask & IN_CREATE)        printf("IN_CREATE ");
          if (i->mask & IN_DELETE)        printf("IN_DELETE ");
          if (i->mask & IN_DELETE_SELF)   printf("IN_DELETE_SELF ");
          if (i->mask & IN_IGNORED)      printf("IN_IGNORED ");
          if (i->mask & IN_ISDIR)      printf("IN_ISDIR ");
          if (i->mask & IN_MODIFY)        printf("IN_MODIFY ");
          if (i->mask & IN_MOVE_SELF)  printf("IN_MOVE_SELF ");
          if (i->mask & IN_MOVED_FROM)    printf("IN_MOVED_FROM ");
          if (i->mask & IN_MOVED_TO)    printf("IN_MOVED_TO ");
          if (i->mask & IN_OPEN)        printf("IN_OPEN ");
          if (i->mask & IN_Q_OVERFLOW)    printf("IN_Q_OVERFLOW ");
          if (i->mask & IN_UNMOUNT)      printf("IN_UNMOUNT ");
          printf("\n");
      
          if (i->len > 0)
              printf("        name = %s\n", i->name);
      }
      
      #define BUF_LEN (10 * (sizeof(struct inotify_event) + NAME_MAX + 1))
      
      static void sigio_handler(int sig)
      {
          char buf[BUF_LEN] __attribute__ ((aligned(8)));
      
          ssize_t numRead = read(inotifyFd, buf, BUF_LEN);
          if (numRead == 0) {
              fprintf(stderr, "read() from inotify fd returned 0!");
          }
      
          if (numRead == -1) {
              fprintf(stderr, "read");
          }
      
          printf("Read %ld bytes from inotify fd\n", (long) numRead);
      
          /* Process all of the events in buffer returned by read() */
      
          for (char *p = buf; p < buf + numRead; ) {
              struct inotify_event *event = (struct inotify_event *) p;
              displayInotifyEvent(event);
              p += sizeof(struct inotify_event) + event->len;
          }
      
      }
      
      int main(int argc, char *argv[])
      {
          if (argc < 2 || strcmp(argv[1], "--help") == 0)
              printf("%s pathname...\n", argv[0]);
      
          inotifyFd = inotify_init();              /* Create inotify instance */
          if (inotifyFd == -1) {
              fprintf(stderr, "inotify_init");
          }
      
          /* Establish handler for "I/O possible" signal */
      
          struct sigaction sa;
          sigemptyset(&sa.sa_mask);
          sa.sa_flags = SA_RESTART;
          sa.sa_handler = sigio_handler;
          if (sigaction(SIGIO, &sa, NULL) == -1) {
              fprintf(stderr, "sigaction");
          }
      
          /* Set owner process that is to receive "I/O possible" signal */
      
          if (fcntl(inotifyFd, F_SETOWN, getpid()) == -1) {
              fprintf(stderr, "fcntl(F_SETOWN)");
          }
      
          /* Enable "I/O possible" signaling and make I/O nonblocking
             for file descriptor */
      
          int flags = fcntl(inotifyFd, F_GETFL);
          if (fcntl(inotifyFd, F_SETFL, flags | O_ASYNC | O_NONBLOCK) == -1) {
              fprintf(stderr, "fcntl(F_SETFL)");
          }
      
          for (int j = 1; j < argc; j++) {
              int wd = inotify_add_watch(inotifyFd, argv[j], IN_ALL_EVENTS);
              if (wd == -1) {
                  fprintf(stderr, "inotify_add_watch");
              }
      
              printf("Watching %s using wd %d\n", argv[j], wd);
          }
      
          while (1) {
              pause();
          }
      
          return EXIT_SUCCESS;
      }
      

      【讨论】: