Linux file Operation monitoring INotify function and realization principle "turn"

Source: Internet
Author: User
Tags inotify

Transferred from: http://blog.chinaunix.net/uid-26585427-id-5012973.html

1. inotify Main function

It is a mechanism that the kernel uses to inform the user of the changes in the file system of the space program.

As we all know, Linux desktop system and MAC or Windows have a lot of unsatisfactory place, in order to improve this situation, the open source community proposed that the user state needs the kernel to provide some mechanism, So that the user can know in a timely manner what happened to the kernel or the underlying hardware device, so as to better manage the device and provide better service to the user, such as HotPlug, Udev and inotify are the demand. Hotplug is a kernel-to-user application advisory on hot-swappable equipment, the mechanism of the occurrence of some events, the desktop system can use it to effectively manage the device, Udev dynamically maintain/dev device files, inotify is a file system change notification mechanism, such as file increase, The deletion of such events can be immediately known to the user, the mechanism is the famous Desktop Search engine project Beagle introduced, and in the Gamin and other projects are applied.
Disadvantage can only monitor a directory or file, cannot monitor all subdirectories under the directory, want to monitor subdirectories must have their own recursive method to add all directories to the monitoring

2. User interface

In the user state, INotify is used by three system calls and file i/operations on the returned file descriptor, and the first step in using INotify is to create the INotify instance:


                int fd = Inotify_init ();        


Each inotify instance corresponds to a separate sorted queue.

File system Change event is called a watches object management, each watch is a two-tuple (target, event mask), the target can be a file or directory, the event mask represents the INotify event that the application wants to focus on, and each bit corresponds to a inotify event. The Watch object is referenced by the watch descriptor and watches is added through the path name of the file or directory. Directory watches will return events that occurred above all the files in that directory.

The following function is used to add a watch:


                int wd = Inotify_add_watch (fd, path, mask);        


FD is the file descriptor returned by Inotify_init (), path is the pathname of the target being monitored (that is, the file name or directory name), mask is the event mask, andeach of the events represented in the header file Linux/inotify.h is defined. You can modify the event mask in the same way, changing the INotify event that you want to be notified. Wd is the watch descriptor.

The following function is used to delete a watch:


        int ret = Inotify_rm_watch (FD, WD);        


FD is the file descriptor returned by Inotify_init (), and WD is the watch descriptor returned by Inotify_add_watch (). Ret is the return value of a function.


A file event is represented by a inotify_event structure, which is obtained by using the usual file read function read by the file descriptor returned by Inotify_init ().

struct Inotify_event {        __s32           wd;             /* Watch Descriptor */        __u32           mask;           /* Watch Mask */        __u32           cookie;         /* Cookie to synchronize the events */        __u32           len;            /* Length (including nulls) of the name */        char            name[0];        /* Stub for possible name */};


The WD in the structure is the watch descriptor for the monitored target, mask is the event mask, Len is the length of the name string, name is the path name of the monitored target, the name field of the structure is a pile, it simply refers to the user aspect of the file name, the file name is variable length, It is actually immediately following the structure, and the file name is populated with 0 to enable the next event structure to be 4-byte aligned. Note that Len also counts the number of padding bytes.


Multiple events can be obtained at one time through a read call, provided the BUF is large enough.


                size_t len = Read (FD, buf, Buf_len);        


BUF is an array pointer to a inotify_event structure, Buf_len specifies the total length to read, the BUF size is at least less than Buf_len, and the number of events returned by the call depends on the Buf_len and the length of the file name in the event. Len is the number of bytes actually read, which is the total length of the obtained event.

You can use Select () or poll () on the file descriptor FD returned by the function inotify_init (), or you can use the IOCTL command fionread on FD to get the length of the current queue. Close (FD) deletes all watch added to the FD and does the necessary cleanup.


                int inotify_init (void);        int inotify_add_watch (int fd, const char *path, __u32 mask);        int inotify_rm_watch (int fd, __u32 mask);        


3. Kernel Implementation principle

In the kernel, each of the INotify instances corresponds to a inotify_device structure:


 struct Inotify_device {wait_queue_head_t wq;            /* Wait queue for I/O */struct IDR IDR;            /* IDR mapping WD--Watch */struct semaphore sem;         /* Protects this bad boy */struct list_head events;        /* List of queued events */struct list_head watches;          /* List of Watches */atomic_t count;          /* Reference count */struct user_struct *user;     /* User who opened this dev */unsigned int queue_size;    /* Size of the queue (bytes) */unsigned int event_count;     /* Number of pending events */unsigned int max_events;        /* Maximum number of events */U32 LAST_WD;
 /* The last WD allocated */}; 


D_list points to the list of all Inotify_device, i_list points to the list of all monitored inode, count is the reference count, and dev points to the inotify_device structure of the inotify instance where the watch is located , the inode points to the watch to monitor the INODE,WD is assigned to the watch descriptor, mask is the event mask of the watch, indicating which file system events it is interested in.

The struct Inotify_device is created when the user state calls Inotify_init () and is freed when the file descriptor returned by Inotify_init () is closed. The struct Inotify_watch is created when the user state calls Inotify_add_watch () and is freed when the user state calls Inotify_rm_watch () or Close (FD).

The inotify system adds two fields to the inode structure, regardless of whether it is a directory or a file, which corresponds to an inode structure in the kernel:



 struct Inotify_wat  ch {struct List_head d_list;/* entry in Inotify_device ' s list */struct list_head i_list;/*  Entry in Inode ' s list */atomic_t count;   /* Reference count */struct inotify_device *dev; /* Associated device */struct inode *inode;     /* Associated Inode */S32 WD;   /* Watch Descriptor */u32 mask;
  /* Event mask for this watch */}; 


D_list points to the list of all Inotify_device, i_list points to the list of all monitored inode, count is the reference count, and dev points to the inotify_device structure of the inotify instance where the watch is located , the inode points to the watch to monitor the INODE,WD is assigned to the watch descriptor, mask is the event mask of the watch, indicating which file system events it is interested in.

The struct Inotify_device is created when the user state calls Inotify_init () and is freed when the file descriptor returned by Inotify_init () is closed. The struct Inotify_watch is created when the user state calls Inotify_add_watch () and is freed when the user state calls Inotify_rm_watch () or Close (FD).

The inotify system adds two fields to the inode structure, regardless of whether it is a directory or a file, which corresponds to an inode structure in the kernel:



#ifdef config_inotifystruct list_headinotify_watches; /* Watches on this inode */struct semaphoreinotify_sem;/* protects the watches list */#endif


Inotify_watches is the watch list on the monitored target, and each time the user calls Inotify_add_watch (), the kernel creates a inotify_watch structure for the added watch and inserts it into the inode for the monitored target. List of inotify_watches. Inotify_sem is used to synchronize access to the Inotify_watches list. When one of the events mentioned in the first part of the file system occurs, the corresponding file system code will display the call to fsnotify_* to report the corresponding event to the inotify system, where the * number is the corresponding event name, and the current implementation includes:

Fsnotify_move, files are moved from one directory to another directory fsnotify_nameremove, files are removed from the directory fsnotify_inoderemove, Fsnotify_create are deleted from the folder, new files are created Fsnotify _mkdir, create new directory fsnotify_access, file is read fsnotify_modify, file is written fsnotify_open, file is opened Fsnotify_close, file is closed fsnotify_xattr, The extended properties of the file are modified Fsnotify_change, the file is modified, or the original data is modified with an exception, that is, Inotify_unmount_inodes, which is called when the file system is umount to notify the Umount event to the inotify system.

The notification functions mentioned above are finally called Inotify_inode_queue_event (Inotify_unmount_inodes call inotify_dev_queue_event directly), The function first determines whether the corresponding inode is monitored, which is accomplished by looking at whether the Inotify_watches list is empty, if the inode is not monitored, does nothing, returns immediately, and, conversely, traverses the inotify_watches list, See if the current file manipulation event is monitored by a watch, and if it is, call inotify_dev_queue_event, otherwise, return. The function Inotify_dev_queue_event first determines whether the event is a repetition of the previous event, discards the event, and returns it, otherwise it determines whether the INotify instance is the Inotify_device event queue overflow, if overflow, An overflow event is generated, otherwise a current file manipulation event is generated, which is built by Kernel_event, Kernel_event creates a inotify_kernel_event structure, and then inserts the structure into the corresponding inotify_ The events list of the device, and then wakes up the wait queue that waits for WQ in the inotify_device structure to point to. The user-state process that wants to monitor file system events is called Read on the INotify instance (that is, the file descriptor returned by Inotify_init (), but no events are hung on the wait queue Wq.

4. Using the example

Here is an example of using INotify to monitor file system events:


#include #include #include _syscall0 (int, inotify_init) _syscall3 (int, inotify_add_watch, int, FD, const char *, PATH, __U3 2, mask) _syscall2 (int, inotify_rm_watch, int, FD, __u32, mask) char * monitored_files[] = {"./tmp_file", "./tmp_dir", "/mnt /sda3/windows_file "};struct wd_name {int Wd;char * name;}; #define WD_NUM 3struct wd_name Wd_array[wd_num];char * event_array[] = {"File is accessed", "File was modified", "File attr  Ibutes were changed "," Writtable file Closed "," unwrittable file Closed "," file was opened "," file is moved from X "," File is Moved to Y "," Subfile was created "," Subfile is deleted "," Self is deleted "," Self is moved "," "," Backing FS was unmounted " , "Event queued overflowed", "File was ignored"}, #define EVENT_NUM 16#define max_buf_size 1024int Main (void) {int fd;int wd; Char Buffer[1024];char * offset = null;struct Inotify_event * event;int len, tmp_len;char strbuf[16];int i = 0;FD = Inotif Y_init (); if (FD < 0) {printf ("Fail to initialize inotify.\n"); exit (-1);} for (i=0; imask& In_isdir) {memcpy (strbuf, "Direcotory", 11);} else {memcpy (strbuf, "File", 5);} printf ("Object type:%s\n", strbuf); for (i=0; IWD! = wd_array[i].wd) continue;printf ("Object name:%s\n", Wd_array[i].nam e); break;} printf ("Event Mask:%08x\n", Event->mask); for (i=0; Imask & (1<len;event = (struct inotify_event *) (offset + tmp_len); offset + = Tmp_len; }}

Linux file Operation monitoring INotify function and realization principle "turn"

Related Article

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.