Article Title: inotify is an essential tool for Linux File System Monitoring. Linux is a technology channel of the IT lab in China. Includes basic categories such as desktop applications, Linux system management, kernel research, embedded systems, and open source.
This article describes how to use inotify to control events in a Linux File System. Before learning more, let's take a look at inotify and its history. We will also introduce the specific application of inotify and solutions for problems encountered.
Inotify Introduction
File System event monitoring is necessary for a variety of programs, from File Manager to security tools. Linux has provided inotify since Kernel 2.6.13, which allows the monitoring program to open an independent file descriptor and monitor one or more files or directories for a series of specific events, for example, open, close, move/rename, delete, create, or change attributes. More enhancements are available in later versions. Therefore, check the kernel version of the system before depending on these features.
In this article, you will learn how to use the inotify function in a simple monitoring program. Download the sample code and compile it in the system to prepare for future research.
History
Dnotify is available before inotify. Unfortunately, dnotify has limitations and cannot meet user needs. inotify has the following advantages:
Inotify uses a simple file descriptor, while dmeany needs to open a file descriptor for each monitored directory. This makes it costly to monitor multiple directories at the same time, and may also encounter file descriptor restrictions for each process.
Inotify uses the file descriptor obtained through the system call, and there is no relevant device or file. For dnotify, the file descriptor has a fixed relationship with the directory, avoiding the problem that related devices are not loaded. This is a typical problem of removable media. For inotify, if the file system in which the monitored file or directory is located is not loaded, an event is generated and the monitoring is automatically removed.
Inotify can monitor files or directories. Dnotify monitors the directory. Therefore, the programmer must maintain the stat structure or equivalent data structure to reflect the monitored files in the directory. Then, when an event occurs, compare it with the current status, to know what happens to the entries in the directory.
As described above, inotify uses file descriptors that allow programmers to monitor events using standard select or poll functions. This allows efficient multi-I/O or integration with Glib mainloop. In contrast, dnotify uses signals, making programmers feel more difficult or not fluent. In kernel 2.6.25, inotify also added the Signal-drive I. O announcement feature.
Inotify APIs
Inotify provides simple APIs that use the smallest file descriptor and allow fine-grained monitoring. Communication with inotify is implemented through system calls.
Inotify_init
Is a system call used to create an inotify instance and returns a file descriptor pointing to the instance.
Inotify_init1
Similar to inotify_init, and with an additional flag. If these flags are not specified, the same value as inotify_init is used.
Inotify_add_watch
Monitors files or directories and specifies which events need to be monitored. The flag is used to control whether to add events to existing monitoring, whether to monitor only a directory represented by a path, whether to track symbolic links, and whether to perform one-time monitoring, when an event occurs for the first time, the monitoring is stopped.
Inotify_rm_watch
Remove a monitoring item from the monitoring list.
Read
Read the cache that contains one or more event information.
Close
Disable the file descriptor and remove all monitoring data on the descriptor. When all file descriptors of an instance are disabled, the resources and lower-level objects will be released for the kernel to use again.
Therefore, a typical monitoring program must perform the following operations:
Use inotify_init to open the file descriptor;
Add one or more monitors;
Wait for the event;
Process the event, then return and wait for more events;
When there is no active monitoring, or based on some signal instructions, disable the file descriptor, clear the file, and then exit.
In the next section, you will see monitored events and how they run in simple programs. Finally, you will see how to perform event monitoring.
Announcement
When an application reads a notification, the event sequence is also read into the cache. The event is returned in a variable-length struct, as shown in Listing 1. If the data is full of cache, local event information or local name processing may be required for the last entry.
List 1. Event struct used for inotify
1. struct inotify_event
2 .{
3. int wd;/* Watch descriptor .*/
4. uint32_t mask;/* Watch mask .*/
5. uint32_t cookie;/* Cookie to synchronize two events .*/
6. uint32_t len;/* Length (including NULs) of name .*/
7. char name _ flexarr;/* Name .*/
8 .};
Note that the name field is provided only when the Monitored object is a directory and the event is related to the project in the directory, but not to the directory itself. If the IN_MOVED_FROM event and the corresponding IN_MOVED_TO event are related to the monitored item, the cookie can be used to associate the two. The event type is returned in the mask field, along with the flag that can be set by the kernel. For example, if the event is related to the directory, it indicates that IN_ISDIR will be set by the kernel.
Events that can be monitored
Several events can be monitored. Some projects, such as IN_DELETE_SELF, can only be applied to monitored projects, while others, such as IN_ATTRIB or IN_OPEN, can be applied to monitored projects, or if the project is a directory, it can be applied to the directory or file it contains.
IN_ACCESS
The entries in the monitored project or monitored Directory have been accessed. For example, an open file is read.
IN_MODIFY
The entries in the monitored project or monitored Directory have been modified. For example, an opened file is modified.
IN_ATTRIB
Metadata of a monitored item or monitored directory has been modified. For example, the timestamp or license is modified.
IN_CLOSE_WRITE
An open file or directory waiting for writing to is closed.
IN_CLOSE_NOWRITE
A file or directory opened in read-only mode is disabled.
IN_CLOSE
Is a mask that can easily perform logic or operations on the two closed events (IN_CLOSE_WRITE | IN_CLOSE_NOWRITE) mentioned above.
IN_OPEN
The file or directory is opened.
IN_MOVED_FROM
Entries in the monitored project or monitored directory are removed from the monitored area. This event also contains a cookie to associate IN_MOVED_FROM with IN_MOVED_TO.
IN_MOVED_TO
Files or directories are moved to the monitoring area. This event contains a cookie for IN_MOVED_FROM. If the file or directory is only renamed, you can see the two events. If it is only moved into or out of the non-monitored area, you can only see one event. If you move or rename a monitored item, monitoring continues. See the IN_MOVE-SELF below.
IN_MOVE
It is a mask that can easily perform logic or operations on the two aforementioned mobile events (IN_MOVED_FROM | IN_MOVED_TO.
IN_CREATE
A subdirectory or file is created in the monitored directory.
IN_DELETE
Subdirectories or files in the monitored directory are deleted.
IN_DELETE_SELF
The monitored project is deleted. Monitoring is terminated and an IN_IGNORED event is received.
IN_MOVE_SELF
The monitoring project itself is moved.
In addition to event flags, you can also find several other flags in the inotify header file (/usr/include/sys/inotify. h. For example, if you only want to monitor the first event, you can set the IN_ONESHOT flag when adding monitoring.
Inotify simple application
The simple application here follows the general logic above. We use a signal processing program to monitor ctrl-c (SIGINT) and reset a flag (keep_running) so that the application understands the termination operation. Real inotify calls are completed in the utility routine. Note: We have also created a queue to clear the event from the underlying inotify object and process it later. In real applications, you may want to use other threads with a higher priority to perform this operation. The applications listed here are only used to illustrate general principles. We use a simple event linked list. Each entry in the queue contains the original event plus the space used to store the next event pointer to the queue.
Main Program
The signal processing program and main program are shown in List 2. In this example, all files or directories that have appeared in the command line are monitored, and the event mask IN_ALL_EVENTS is used to monitor all events of each object. In real applications, you may only want to track file and directory Creation or Deletion events, so you can hide open, close, and attribute change events. If you are not interested in renaming and moving files or directories, you can also hide various mobile events. For more information, see inotify help.
Listing 2. Simple master program for the inotify-test.c
1./* Signal handler that simply resets a flag to cause termination */
2. void signal_handler (int signum)
3 .{
4. keep_running = 0;
5 .}
6. int main (int argc, char ** argv)
7 .{
8./* This is the file descriptor for the inotify watch */
9. int inotify_fd;
10. keep_running = 1;
11./* Set a ctrl-c signal handler */
12. if (signal (SIGINT, signal_handler) = SIG_IGN)
13 .{
14./* Reset to SIG_IGN (ignore) if that was the prior state */
15. signal (SIGINT, SIG_IGN );
16 .}
17./* First we open the inotify dev entry */
18. inotify_fd = open_inotify_fd ();
19. if (inotify_fd> 0)
20 .{
21./* We will need a place to enqueue inotify events,
22. this is needed because if you do not read events
23. fast enough, you will miss them. This queue is
24. probably too small if you are monitoring something
25. like a directory with a lot of files and the directory
26. is deleted.
27 .*/
28. queue_t q;
29. q = queue_create (128 );
30./* This is the watch descriptor returned for each item we are
31. watching. A real application might keep these for some use
32. in the application. This sample only makes sure that none
33. the watch descriptors is less than 0.
34 .*/
35. int wd;
36./* Watch all events (IN_ALL_EVENTS) for the directories and
37. files passed in as arguments.
38. Read the article for why you might want to alter this
39. more efficient inotify use in your app.
40 .*/
41. int index;
42. wd = 0;
43. printf ("\ n ");
44. for (index = 1; (index <argc) & (wd> = 0); index ++)
45 .{
46. wd = watch_dir (inotify_fd, argv [index], IN_ALL_EVENTS );
47 .}
48. if (wd> 0)
49 .{
50./* Wait for events and process them until
51. termination condition is detected
52 .*/
53. process_inotify_events (q, inotify_fd );
54 .}
55. printf ("\ nTerminating \ n ");
56./* Finish up by closing the fd, destroying the queue,
57. and returning a proper code
58 .*/
59. close_inotify_fd (inotify_fd );
60. queue_destroy (q );
61 .}
62. return 0;
63 .}
[1] [2] [3] [4] Next page