Understanding Linux dnotify: Predecessor to inotify
This article examines the legacy dnotify (Directory
Notification) subsystem in the Linux operating system, detailing its
architectural implementation, event-handling mechanics, and historical
significance. Introduced in Linux kernel 2.4, dnotify was
the kernel's first native solution for monitoring filesystem changes.
Below is a breakdown of how the mechanism functions, how applications
interact with it via system calls, and the technical limitations that
necessitated its replacement by inotify.
The Core Architecture of dnotify
The dnotify mechanism operates entirely through the
standard file descriptor architecture and the fcntl system
call. Unlike modern monitoring interfaces that use dedicated file
descriptors for event queues, dnotify attaches
event-monitoring masks directly to directory file descriptors already
opened by a user-space process.
To initialize monitoring, a program opens a target directory using
open() to obtain a file descriptor and then issues an
fcntl command:
fcntl(fd, F_NOTIFY, DN_MODIFY | DN_CREATE | DN_DELETE | DN_MULTISHOT);The third argument is a bitmask of events that the kernel should observe. Supported event flags include:
DN_ACCESS: File inside directory was accessed.DN_MODIFY: File inside directory was modified.DN_CREATE: File was created or moved into the directory.DN_DELETE: File was unlinked or removed from the directory.DN_RENAME: File was renamed within the directory.DN_ATTRIB: File metadata or permissions changed.DN_MULTISHOT: Keeps the watch active after an event occurs (by default, watches are one-shot).
Event Delivery via Signals
Instead of using a readable event stream, dnotify relies
on POSIX signals to alert user-space applications. By default, the
kernel emits a SIGIO signal to the process when an event
matches the configured bitmask.
Because SIGIO provides no contextual information about
the event, developers typically reconfigured the notification signal to
a real-time signal (ranging from SIGRTMIN to
SIGRTMAX) using fcntl(fd, F_SETSIG, signum).
Real-time signals allow queuing and carry an accompanying
siginfo_t structure. This structure passes the file
descriptor of the modified directory to the signal handler via the
si_fd field, allowing the application to identify which
watched directory generated the alert.
Operational Limitations of dnotify
While dnotify provided an improvement over continuous
filesystem polling, several fundamental architectural constraints
limited its scalability and reliability:
- Lack of Granularity: The signal delivered by
dnotifyonly indicates that a change occurred within a directory; it does not identify which specific file inside the directory was modified, added, or deleted. The user application must maintain an in-memory snapshot of directory contents and runstat()orreaddir()across the entire directory upon receiving a signal to determine what changed. - File Pinning and Unmounting:
dnotifyrequires keeping an open file descriptor on every monitored directory. An open file descriptor locks the corresponding mount point, preventing removable media from being unmounted and complicating storage management. - Signal Complexity and Race Conditions: Handling asynchronous signals in complex, multi-threaded applications introduces severe race conditions and reentrancy challenges. Rapid bursts of filesystem activity could overflow standard signal queues, leading to lost events.
- No Direct File Monitoring:
dnotifycan only monitor directories, not individual files. To track changes to a single file, an application must monitor the parent directory and filter out irrelevant events.
Transition to inotify and fanotify
Due to these inefficiencies, dnotify was superseded by
inotify in Linux kernel 2.6.13. inotify
addressed these weaknesses by abandoning signal-based delivery in favor
of a dedicated file descriptor that outputs a structured event stream
via read(), provides specific filenames with events, and
avoids pinning filesystems. Although retained in modern kernels for
backward compatibility, dnotify is considered obsolete and
has been entirely replaced in production software by
inotify and fanotify.