inotify监控Linux文件系统的必备利器(2)
时间:2010-08-26 来源:mydear
inotify 简单应用
这里的简单应用遵循以上的通用逻辑。 我们使用一个信号处理程序来监控 ctrl-c(SIGINT)并且 重置一个标志(keep_running)使应用了解终止操作。 真实的 inotify 调用在 utility 例程当中完成。注意, 我们还创建了一个队列,这样能够将事件从 inotify 底层对象中清除,留着稍后处理。在真实的应用当中,您可能希望用其他(具有更高优先级)的线程来完成这一操作。 这里的列举的应用程序,只是为了对一般原理进行举例说明。我们采用了一个简单的事件链表, 队列中的每一条目都包含原始事件加上用于存储指向队列中下一事件指针的空间。
主程序
清单 2 中展示了信号处理程序和主程序。在本例当中,对所有在命令行中出现过的文件或目录进行监控, 并利用事件掩码 IN_ALL_EVENTS 来监控每一对象的所有事件。 在真实的应用程序中,您可能只希望追踪文件与目录的创建或删除事件,因此您可以掩去打开、关闭以及属性改变事件。 如果您对文件或目录的重命名和移动不感兴趣,您也可以掩去各种移动事件。关于更多细节,参见 inotify 帮助信息。
清单 2. inotify-test.c 的简单主程序
- /* Signal handler that simply resets a flag to cause termination */
- void signal_handler (int signum)
- {
- keep_running = 0;
- }
- int main (int argc, char **argv)
- {
- /* This is the file descriptor for the inotify watch */
- int inotify_fd;
- keep_running = 1;
- /* Set a ctrl-c signal handler */
- if (signal (SIGINT, signal_handler) == SIG_IGN)
- {
- /* Reset to SIG_IGN (ignore) if that was the prior state */
- signal (SIGINT, SIG_IGN);
- }
- /* First we open the inotify dev entry */
- inotify_fd = open_inotify_fd ();
- if (inotify_fd > 0)
- {
- /* We will need a place to enqueue inotify events,
- this is needed because if you do not read events
- fast enough, you will miss them. This queue is
- probably too small if you are monitoring something
- like a directory with a lot of files and the directory
- is deleted.
- */
- queue_t q;
- q = queue_create (128);
- /* This is the watch descriptor returned for each item we are
- watching. A real application might keep these for some use
- in the application. This sample only makes sure that none of
- the watch descriptors is less than 0.
- */
- int wd;
- /* Watch all events (IN_ALL_EVENTS) for the directories and
- files passed in as arguments.
- Read the article for why you might want to alter this for
- more efficient inotify use in your app.
- */
- int index;
- wd = 0;
- printf("n");
- for (index = 1; (index < argc) && (wd >= 0); index++)
- {
- wd = watch_dir (inotify_fd, argv[index], IN_ALL_EVENTS);
- }
- if (wd > 0)
- {
- /* Wait for events and process them until a
- termination condition is detected
- */
- process_inotify_events (q, inotify_fd);
- }
- printf ("nTerminatingn");
- /* Finish up by closing the fd, destroying the queue,
- and returning a proper code
- */
- close_inotify_fd (inotify_fd);
- queue_destroy (q);
- }
- return 0;
- }
利用 inotify_init 打开文件描述符
清单 3 展示了用于创建 inotify 实例的简单应用函数,并为其获得一个文件描述符。文件描述符返回给了调用者。 如果出现错误,返回值将为负。
清单 3. 使用 inotify_init
- /* Create an inotify instance and open a file descriptor
- to access it */
- int open_inotify_fd ()
- {
- int fd;
- watched_items = 0;
- fd = inotify_init ();
- if (fd < 0)
- {
- perror ("inotify_init () = ");
- }
- return fd;
- }
利用 inotify_add_watch 来增加监控
有了用于 inotify 实例的文件描述符之后,就需要增加一个或多个监控。 可以使用掩码来设置想要监控的事件。在本例当中,采用掩码 IN_ALL_EVENTS,来监控全部的有效事件。
清单 4. 使用 inotify_add_watch
- int watch_dir (int fd, const char *dirname, unsigned long mask)
- {
- int wd;
- wd = inotify_add_watch (fd, dirname, mask);
- if (wd < 0)
- {
- printf ("Cannot add watch for "%s" with event mask %lX", dirname,
- mask);
- fflush (stdout);
- perror (" ");
- }
- else
- {
- watched_items++;
- printf ("Watching %s WD=%dn", dirname, wd);
- printf ("Watching = %d itemsn", watched_items);
- }
- return wd;
- }