文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>inotify监控Linux文件系统的必备利器(3)

inotify监控Linux文件系统的必备利器(3)

时间:2010-08-26  来源:mydear

事件处理循环

现在我们已经设置了一些监控,接下来就要等待事件。如果还存在监控,并且 keep_running 标志没有被信号处理程序重置,则循环会一直进行。循环进程等待事件的发生,对有效事件进行排队,并在返回等待状态之前并处理队列。 在真实应用程序当中,可能会采用一个线程将事件放入队列,而采用另一个线程处理它们,清单 5 展示了该循环。

清单 5. 事件处理循环

  1. int process_inotify_events (queue_t q, int fd)
  2. {
  3. while (keep_running && (watched_items > 0))
  4. {
  5. if (event_check (fd) > 0)
  6. {
  7. int r;
  8. r = read_events (q, fd);
  9. if (r < 0)
  10. {
  11. break;
  12. }
  13. else
  14. {
  15. handle_events (q);
  16. }
  17. }
  18. }
  19. return 0;
  20. }

等待事件

在本程序中,循环会不停地进行下去,直至发生被监控事件或者收到了中断信号。清单 6 展示了相关代码。

清单 6. 等待事件或中断

  1. int event_check (int fd)
  2. {
  3. fd_set rfds;
  4. FD_ZERO (&rfds);
  5. FD_SET (fd, &rfds);
  6. /* Wait until an event happens or we get interrupted
  7. by a signal that we catch */
  8. return select (FD_SETSIZE, &rfds, NULL, NULL, NULL);
  9. }

读取事件

当事件发生时,程序会依照缓存区的大小来读取尽量多的事件,然后把这些事件放入队列等待事件处理程序来处理。 样例代码对于事件量大于 16.384-byte 之类的问题不作处理。 想处理这类问题,需要在缓存末端处理局部事件。当前对名字长度所做的限制没有问题,但是优秀的防御式编程会检查名字,来确保不会出现缓存区溢出。

清单 7. 读取事件并排队

  1. int read_events (queue_t q, int fd)
  2. {
  3. char buffer[16384];
  4. size_t buffer_i;
  5. struct inotify_event *pevent;
  6. queue_entry_t event;
  7. ssize_t r;
  8. size_t event_size, q_event_size;-
  9. int count = 0;
  10. r = read (fd, buffer, 16384);
  11. if (r <= 0)
  12. return r;
  13. buffer_i = 0;
  14. while (buffer_i < r)
  15. {
  16. /* Parse events and queue them. */
  17. pevent = (struct inotify_event *) &buffer[buffer_i];
  18. event_size = offsetof (struct inotify_event, name) + pevent->len;
  19. q_event_size = offsetof (struct queue_entry, inot_ev.name) +
  20. pevent->len;
  21. event = malloc (q_event_size);
  22. memmove (&(event->inot_ev), pevent, event_size);
  23. queue_enqueue (event, q);
  24. buffer_i += event_size;
  25. count++;
  26. }
  27. printf ("n%d events queuedn", count);
  28. return count;
  29. }

处理事件

最终,需要对事件做处理。本例中的应用程序不处理事件,只报告发生了哪些事件。如果事件结构体中有一个名字出现, 程序将报告其是目录还是文件。在发生移动操作时,还会报告与移动或重命名事件相关的 cookie 信息。 清单 8 展示了部分代码,包括对一些事件的处理。参见 下载 部分可获得全部代码。

清单 8. 处理事件

  1. void handle_event (queue_entry_t event)
  2. {
  3. /* If the event was associated with a filename, we will
    store it here */
  4. char *cur_event_filename = NULL;
  5. char *cur_event_file_or_dir = NULL;
  6. /* This is the watch descriptor the event occurred on */
  7. int cur_event_wd = event->inot_ev.wd;
  8. int cur_event_cookie = event->inot_ev.cookie;
  9. unsigned long flags;
  10. if (event->inot_ev.len)
  11. {
  12. cur_event_filename = event->inot_ev.name;
  13. }
  14. if ( event->inot_ev.mask & IN_ISDIR )
  15. {
  16. cur_event_file_or_dir = "Dir";
  17. }
  18. else
  19. {
  20. cur_event_file_or_dir = "File";
  21. }
  22. flags = event->inot_ev.mask &
  23. ~(IN_ALL_EVENTS | IN_UNMOUNT | IN_Q_OVERFLOW | IN_IGNORED );
  24. /* Perform event dependent handler routines */
  25. /* The mask is the magic that tells us what file operation
    occurred */
  26. switch (event->inot_ev.mask &
  27. (IN_ALL_EVENTS | IN_UNMOUNT | IN_Q_OVERFLOW | IN_IGNORED))
  28. {
  29. /* File was accessed */
  30. case IN_ACCESS:
  31. printf ("ACCESS: %s "%s" on WD #%in",
  32. cur_event_file_or_dir, cur_event_filename, cur_event_wd);
  33. break;
  34. /* File was modified */
  35. case IN_MODIFY:
  36. printf ("MODIFY: %s "%s" on WD #%in",
  37. cur_event_file_or_dir, cur_event_filename, cur_event_wd);
  38. break;
  39. /* File changed attributes */
  40. case IN_ATTRIB:
  41. printf ("ATTRIB: %s "%s" on WD #%in",
  42. cur_event_file_or_dir, cur_event_filename, cur_event_wd);
  43. break;
  44. /* File open for writing was closed */
  45. case IN_CLOSE_WRITE:
  46. printf ("CLOSE_WRITE: %s "%s" on WD #%in",
  47. cur_event_file_or_dir, cur_event_filename, cur_event_wd);
  48. break;
  49. /* File open read-only was closed */
  50. case IN_CLOSE_NOWRITE:
  51. printf ("CLOSE_NOWRITE: %s "%s" on WD #%in",
  52. cur_event_file_or_dir, cur_event_filename, cur_event_wd);
  53. break;
  54. /* File was opened */
  55. case IN_OPEN:
  56. printf ("OPEN: %s "%s" on WD #%in",
  57. cur_event_file_or_dir, cur_event_filename, cur_event_wd);
  58. break;
  59. /* File was moved from X */
  60. case IN_MOVED_FROM:
  61. printf ("MOVED_FROM: %s "%s" on WD #%i. Cookie=%dn",
  62. cur_event_file_or_dir, cur_event_filename, cur_event_wd,
  63. cur_event_cookie);
  64. break;
  65. .
  66. . (other cases)
  67. .
  68. /* Watch was removed explicitly by inotify_rm_watch or
    automatically
  69. because file was deleted, or file system was unmounted. */
  70. case IN_IGNORED:
  71. watched_items--;
  72. printf ("IGNORED: WD #%dn", cur_event_wd);
  73. printf("Watching = %d itemsn",watched_items);
  74. break;
  75. /* Some unknown message received */
  76. default:
  77. printf ("UNKNOWN EVENT "%X" OCCURRED for file "%s" on WD #%in",
  78. event->inot_ev.mask, cur_event_filename, cur_event_wd);
  79. break;
  80. }
  81. /* If any flags were set other than IN_ISDIR, report the flags */
  82. if (flags & (~IN_ISDIR))
  83. {
  84. flags = event->inot_ev.mask;
  85. printf ("Flags=%lXn", flags);
  86. }
  87. }
该例子用来举例说明 inotify 如何工作以及能够监控哪些事件。 您的实际需求将决定对哪些事件进行监控以及如何处理这些事件。
相关阅读 更多 +
排行榜 更多 +
辰域智控app

辰域智控app

系统工具 下载
网医联盟app

网医联盟app

运动健身 下载
汇丰汇选App

汇丰汇选App

金融理财 下载