Use inotify to monitor Linux File System Events

Source: Internet
Author: User

 

Inotify is a file system event monitoring mechanism and is planned to be included in the forthcoming Linux kernel as an effective replacement for dnotify. Dnotify is a file monitoring mechanism supported by earlier kernels. Inotify is a powerful, fine-grained, asynchronous mechanism that meets various file monitoring needs, not limited to security and performance. Next let's learn how to install inotify and how to build an example user space application to respond to file system events.

File System event monitoring is necessary for various programs from File Manager to security tools, but dnotify (standard in earlier kernels) has some limitations, this makes us look forward to a more comprehensive mechanism. With this expectation, we foundInotify, A more modern alternative to file system event monitoring.

Why inotify?

There are many reasons for replacing dnotify with inotify. The first reason is that dnotify requires you to open a file descriptor for each directory to be monitored for change. When multiple directories are monitored at the same time, this consumes a lot of resources because it may limit the file descriptor of each process.

In addition, the file descriptor locks the Directory and does not allow unmount. This causes problems in the environment where removable media exists. When inotify is used, if you are monitoring files on the uninstalled file system, the monitoring will be automatically removed and you will receive an unload event.

The second reason why dnotify is not as complex as inotify is that dnotify is a bit complicated. Note that the monitoring granularity of a simple File System Using the dnotify infrastructure is only at the directory level. To use dnotify for more fine-grained monitoring, application programmers must keep onestatStructure cache. ThestatThe structure cache needs to be used to determine the directory changes when a notification signal is received. Generated when a notification signal is obtainedstatStructure list and compare it with the latest status. Obviously, this technology is not ideal.

Another advantage of inotify is that it uses file descriptors as the basic interface for application developers to useselectAndpollTo monitor the device. This allows effective multiline I/O andmainloop. On the contrary, the signals used by dnotify often make programmers feel a headache and not very elegant.

Inotify solves these problems by providing a more elegant API that uses the least file descriptor and ensures more fine-grained monitoring. The communication with inotify is provided by the device node. For the above reasons, inotify is your best choice for monitoring files on Linux 2.6.



Back to Top

Install inotify

The first step to install inotify is to determine whether your Linux kernel supports inotify. The easiest way to check the release is to find whether the/dev/inotify device exists. If this device exists, you can jump to the inotify section in a simple application.

At the time of writing this article, inotify was included in the Linux 2.6-mm directory tree of Andrew Morton, and some Linux distributions are providing kernels (including Gentoo and UBUNTU) that support inotify) or you can have a supported supplemental kernel package (such as fedora and SUSE ). Because Andrew may remove inotify support from the directory tree as needed, and the inotify version is still in frequent development stages, we strongly recommend that you install patches from the beginning.

If the device is missing, you may need to patch the kernel and create the device.

Patch inotify Kernel

Inotify patches can be obtained from Linux kernel archives (see the link in the references section ).

You should apply the patch with the highest version number for a specific kernel. Each release version processes different kernel installation, but the following describes a general guide.Note:Obtain the Linux kernel source file of release version 2.6 from Linux kernel archives. If applicable, obtain the latest stable version.

Start from entering the kernel source file directory:

bash:~$ cd /usr/src

Because you have installed the kernel source file earlier, you need to decompress it now:

bash:~$ sudo tar jxvf linux-source-2.6.8.1.tar.bz2

Now, point your symlink to the new source file directory tree:

bash:~$ sudo ln -sf linux-source-2.6.8.1 linux

Change the current directory to the created kernel source file directory:

bash:~$ cd linux

Copy inotify patch:

bash:~$ sudo cp ~/inotify* /usr/src

Patch the kernel:

bash:~$ sudo patch -p1 < ../inotify*.patch

Build the kernel:

bash:~$ sudo make menuconfig

Configure your kernel as usual to ensure that inotify works properly. If necessary, add the new kernel to the boot loader, but remember to maintain the image and boot loader options of the old kernel. This step varies with different boot loaders (see references for more information about specific boot loaders ). Reboot the computer and select a new kernel that enables inotify. Before proceeding, test your new kernel to make sure it works properly.

Create an inotify Device

Next, make sure to create the/dev/inotify device. Follow these steps to complete the process.Important:The device number may change, so you need to pay more attention to make sure it is updated at any time! If Linux installation supports the udev function, it automatically keeps updated.

After you reboot to the new kernel, you must obtain the device Number:

bash:~$ dmesg | grep ^inotify

Example of returned results:

inotify device minor=63

Because inotify ismiscDevice, so the master device number is 10. To create a device node as the root user, run the following command:

bash:~$ mknod /dev/inotify c 10 63

Note:If necessary, replace "63" with the appropriate device number ".

You can set the permissions you want at will. The following is an example of permission settings:

bash:~$ chown root:root /dev/inotify
bash:~$ chmod 666 /dev/inotify

You are now ready to use the inotify device for file system monitoring.



Back to Top

Use inotify in simple applications

To demonstrate the use of inotify, I will show how to construct a sample program that monitors arbitrary directories (or individual files) for file system events. I will stand at a high level to show how easy inotify makes file system monitoring.

Main Method

This simple example shows how easy inotify is to set monitoring in any directory. We will see the main helper routine later. You can obtain the sample code used in these examples in the download section of this article.

List 1. Set monitoring on the directory

            /* This program will take as argument a directory name and monitor it,            printing event notifications to the console.            */            int main (int argc, char **argv)            {            /* This is the file descriptor for the inotify device */            int inotify_fd;            /* First we open the inotify dev entry */            inotify_fd = open_inotify_dev();            if (inotify_fd < 0)            {            return 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.            */            queue_t q;            q = queue_create (128);            /* Watch the directory passed in as argument            Read on for why you might want to alter this for            more efficient inotify use in your app.            */            watch_dir (inotify_fd, argv[1], ALL_MASK);            process_inotify_events (q, inotify_fd);            /* Finish up by destroying the queue, closing the fd,            and returning a proper code            */            queue_destroy (q);            close_inotify_dev (inotify_fd);            return 0;            }            

Important helper Methods

The following are the most important helper routines shared by inotify-based applications:

  • Enable the inotify device for reading.
  • Queues events read from this device.
  • The actual processor per event that allows applications to effectively process event notifications.

I will not delve into the details of event queuing, because we can use some policies to avoid queuing. The provided code shows this method. More advanced multi-threaded methods can be implemented elsewhere. In those implementations, the reader thread simply runs on the inotify Deviceselect()And then copy the event to some storage space shared by the thread (or something like the asynchronous message queue of glib). Then the processor thread will process the event here.

Listing 2. Enable the inotify Device

            /* This simply opens the inotify node in dev (read only) */            int open_inotify_dev ()            {            int fd;            fd = open("/dev/inotify", O_RDONLY);            if (fd < 0)            {            perror ("open(\"/dev/inotify\", O_RDONLY) = ");            }            return fd;            }            

This should be familiar to anyone who has programmed files on Linux.

Listing 3. Actual event processing routine

            /* This method does the dirty work of determining what happened,            then allows us to act appropriately            */            void handle_event (struct inotify_event *event)            {            /* If the event was associated with a filename, we will store it here */            char * cur_event_filename = NULL;            /* This is the watch descriptor the event occurred on */            int cur_event_wd = event->wd;            if (event->len)            {            cur_event_filename = event->filename;            }            printf("FILENAME=%s\n", cur_event_filename);            printf("\n");            /* Perform event dependent handler routines */            /* The mask is the magic that tells us what file operation occurred */            switch (event->mask)            {            /* File was accessed */            case IN_ACCESS:            printf("ACCESS EVENT OCCURRED: File \"%s\" on WD #%i\n",            cur_event_filename, cur_event_wd);            break;            /* File was modified */            case IN_MODIFY:            printf("MODIFY EVENT OCCURRED: File \"%s\" on WD #%i\n",            cur_event_filename, cur_event_wd);            break;            /* File changed attributes */            case IN_ATTRIB:            printf("ATTRIB EVENT OCCURRED: File \"%s\" on WD #%i\n",            cur_event_filename, cur_event_wd);            break;            /* File was closed */            case IN_CLOSE:            printf("CLOSE EVENT OCCURRED: File \"%s\" on WD #%i\n",            cur_event_filename, cur_event_wd);            break;            /* File was opened */            case IN_OPEN:            printf("OPEN EVENT OCCURRED: File \"%s\" on WD #%i\n",            cur_event_filename, cur_event_wd);            break;            /* File was moved from X */            case IN_MOVED_FROM:            printf("MOVE_FROM EVENT OCCURRED: File \"%s\" on WD #%i\n",            cur_event_filename, cur_event_wd);            break;            /* File was moved to X */            case IN_MOVED_TO:            printf("MOVE_TO EVENT OCCURRED: File \"%s\" on WD #%i\n",            cur_event_filename, cur_event_wd);            break;            /* Subdir was deleted */            case IN_DELETE_SUBDIR:            printf("DELETE_SUBDIR EVENT OCCURRED: File \"%s\" on WD #%i\n",            cur_event_filename, cur_event_wd);            break;            /* File was deleted */            case IN_DELETE_FILE:            printf("DELETE_FILE EVENT OCCURRED: File \"%s\" on WD #%i\n",            cur_event_filename, cur_event_wd);            break;            /* Subdir was created */            case IN_CREATE_SUBDIR:            printf("CREATE_SUBDIR EVENT OCCURRED: File \"%s\" on WD #%i\n",            cur_event_filename, cur_event_wd);            break;            /* File was created */            case IN_CREATE_FILE:            printf("CREATE_FILE EVENT OCCURRED: File \"%s\" on WD #%i\n",            cur_event_filename, cur_event_wd);            break;            /* Watched entry was deleted */            case IN_DELETE_SELF:            printf("DELETE_SELF EVENT OCCURRED: File \"%s\" on WD #%i\n",            cur_event_filename, cur_event_wd);            break;            /* Backing FS was unmounted */            case IN_UNMOUNT:            printf("UNMOUNT EVENT OCCURRED: File \"%s\" on WD #%i\n",            cur_event_filename, cur_event_wd);            break;            /* Too many FS events were received without reading them            some event notifications were potentially lost.  */            case IN_Q_OVERFLOW:            printf("Warning: AN OVERFLOW EVENT OCCURRED: \n");            break;            case IN_IGNORED:            printf("IGNORED EVENT OCCURRED: \n");            break;            /* Some unknown message received */            default:            printf ("UNKNOWN EVENT OCCURRED for file \"%s\" on WD #%i\n",            cur_event_filename, cur_event_wd);            break;            }            }            

In eachcaseYou can execute any methods that have been implemented and meet your needs.

As for performance monitoring, you can determine which files are most frequently read and their opening duration. This kind of monitoring is very convenient, because in some cases, if the file is repeatedly read by the application within a short period of time, it will cache the file in the memory instead of returning the disk for reading, to improve performance.

It is easy to give examples of event-specific processors that execute interesting operations. For example, if you are implementing a metadata storage index for the underlying file system, you may find a file creation event and trigger a metadata mining operation on the file soon. In a secure environment, if a file is written to a directory that nobody can write, you will trigger some forms of system alarms.

Note that inotify supports many very fine-grained events-for exampleCLOSEAndCLOSE_WRITE.

The code in this article lists many events that you may not want to see every time you run the code. In fact, as long as possible, you can and should only request a subset of events that are useful to your application. For testing purposes, the Code provided in this article uses the full mask strictly (for example, the sample code that can be downloaded [see references ]).mainA number of events are displayed. Application programmers usually want to have more options, and you need a more specific mask to meet your needs. This allows youhandle_event()Methods.


Conclusion

Inotify is a powerful and fine-grained mechanism used to monitor Linux file systems when applied to performance monitoring, debugging, and automation. With the Code provided in this article, you can write applications that can respond to or record file system events with the lowest performance overhead.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.