Путеводитель по Руководству Linux

  User  |  Syst  |  Libr  |  Device  |  Files  |  Other  |  Admin  |  Head  |



   inotify    ( 7 )

мониторинг событий файловой системы (monitoring filesystem events)

  Name  |  Description  |  Versions  |  Conforming to  |    Note    |  Bugs  |  Examples  |  See also  |

Примечание (Note)

Inotify file descriptors can be monitored using select(2), poll(2), and epoll(7). When an event is available, the file descriptor indicates as readable.

Since Linux 2.6.25, signal-driven I/O notification is available for inotify file descriptors; see the discussion of F_SETFL (for setting the O_ASYNC flag), F_SETOWN, and F_SETSIG in fcntl(2). The siginfo_t structure (described in sigaction(2)) that is passed to the signal handler has the following fields set: si_fd is set to the inotify file descriptor number; si_signo is set to the signal number; si_code is set to POLL_IN; and POLLIN is set in si_band.

If successive output inotify events produced on the inotify file descriptor are identical (same wd, mask, cookie, and name), then they are coalesced into a single event if the older event has not yet been read (but see BUGS). This reduces the amount of kernel memory required for the event queue, but also means that an application can't use inotify to reliably count file events.

The events returned by reading from an inotify file descriptor form an ordered queue. Thus, for example, it is guaranteed that when renaming from one directory to another, events will be produced in the correct order on the inotify file descriptor.

The set of watch descriptors that is being monitored via an inotify file descriptor can be viewed via the entry for the inotify file descriptor in the process's /proc/[pid]/fdinfo directory. See proc(5) for further details. The FIONREAD ioctl(2) returns the number of bytes available to read from an inotify file descriptor.

Limitations and caveats The inotify API provides no information about the user or process that triggered the inotify event. In particular, there is no easy way for a process that is monitoring events via inotify to distinguish events that it triggers itself from those that are triggered by other processes.

Inotify reports only events that a user-space program triggers through the filesystem API. As a result, it does not catch remote events that occur on network filesystems. (Applications must fall back to polling the filesystem to catch such events.) Furthermore, various pseudo-filesystems such as /proc, /sys, and /dev/pts are not monitorable with inotify.

The inotify API does not report file accesses and modifications that may occur because of mmap(2), msync(2), and munmap(2).

The inotify API identifies affected files by filename. However, by the time an application processes an inotify event, the filename may already have been deleted or renamed.

The inotify API identifies events via watch descriptors. It is the application's responsibility to cache a mapping (if one is needed) between watch descriptors and pathnames. Be aware that directory renamings may affect multiple cached pathnames.

Inotify monitoring of directories is not recursive: to monitor subdirectories under a directory, additional watches must be created. This can take a significant amount time for large directory trees.

If monitoring an entire directory subtree, and a new subdirectory is created in that tree or an existing directory is renamed into that tree, be aware that by the time you create a watch for the new subdirectory, new files (and subdirectories) may already exist inside the subdirectory. Therefore, you may want to scan the contents of the subdirectory immediately after adding the watch (and, if desired, recursively add watches for any subdirectories that it contains).

Note that the event queue can overflow. In this case, events are lost. Robust applications should handle the possibility of lost events gracefully. For example, it may be necessary to rebuild part or all of the application cache. (One simple, but possibly expensive, approach is to close the inotify file descriptor, empty the cache, create a new inotify file descriptor, and then re-create watches and cache entries for the objects to be monitored.)

If a filesystem is mounted on top of a monitored directory, no event is generated, and no events are generated for objects immediately under the new mount point. If the filesystem is subsequently unmounted, events will subsequently be generated for the directory and the objects it contains.

Dealing with rename() events As noted above, the IN_MOVED_FROM and IN_MOVED_TO event pair that is generated by rename(2) can be matched up via their shared cookie value. However, the task of matching has some challenges.

These two events are usually consecutive in the event stream available when reading from the inotify file descriptor. However, this is not guaranteed. If multiple processes are triggering events for monitored objects, then (on rare occasions) an arbitrary number of other events may appear between the IN_MOVED_FROM and IN_MOVED_TO events. Furthermore, it is not guaranteed that the event pair is atomically inserted into the queue: there may be a brief interval where the IN_MOVED_FROM has appeared, but the IN_MOVED_TO has not.

Matching up the IN_MOVED_FROM and IN_MOVED_TO event pair generated by rename(2) is thus inherently racy. (Don't forget that if an object is renamed outside of a monitored directory, there may not even be an IN_MOVED_TO event.) Heuristic approaches (e.g., assume the events are always consecutive) can be used to ensure a match in most cases, but will inevitably miss some cases, causing the application to perceive the IN_MOVED_FROM and IN_MOVED_TO events as being unrelated. If watch descriptors are destroyed and re-created as a result, then those watch descriptors will be inconsistent with the watch descriptors in any pending events. (Re-creating the inotify file descriptor and rebuilding the cache may be useful to deal with this scenario.)

Applications should also allow for the possibility that the IN_MOVED_FROM event was the last event that could fit in the buffer returned by the current call to read(2), and the accompanying IN_MOVED_TO event might be fetched only on the next read(2), which should be done with a (small) timeout to allow for the fact that insertion of the IN_MOVED_FROM+IN_MOVED_TO event pair is not atomic, and also the possibility that there may not be any IN_MOVED_TO event.