Linux inotify function and implementation principle

Source: Internet
Author: User
Tags inotify

Http://www.cnblogs.com/jiejnan/archive/2012/05/18/2507476.html

Summary: when it comes to high-efficiency, fine-grained, asynchronous monitoring of Linux file systems, INotify can be used. It can be used for security, performance, and other monitoring of user space.

As for the basic introduction of inotify can see the following link

http://www.ibm.com/developerworks/cn/linux/l-inotify/index.html?ca=drs-

Here is the main conclusion of their own experiments:

    1. When to call Inotify_rm_watch yourself
    2. Appropriate to call Inotify_add_watch yourself
    3. Read invocation Considerations

For 1, when there is moved_from and no moved_to, it is necessary to call Inotify_rm_watch to remove the removed directory (moved to the non-monitoring directory) to monitor the deletion, the directory below the subdirectory will be automatically deleted. Like other operations: Delete the monitoring directory, the monitoring directory in the large monitoring directory in the move-out is not required to call Inotify_rm_watch itself, because the system automatically processed, the resulting events are delete_self and move_self.

For 2, it depends on whether you need to recursively monitor each directory, if so, when you create a new directory under the Monitoring directory, you need to call Inotify_add_watch, the system does not have a separate moved_to, If you copy a directory from the non-monitored directory to the Monitoring directory, then the event generated by INotify is create (directory or file), not moved_to, but can generate moved_from events individually, as described in Scenario 1.

To with 3, to know the following red limits,

/PROC interfaces
The following interfaces can be used to limit the amount of kernel memory consumed by inotify:

/proc/sys/fs/inotify/max_queued_events
The value of this file was used when an application calls Inotify_init (2) to set a upper limit on the number of events That can is queued to the corresponding inotify instance. Events in excessof the This limit was dropped, but an N_q_overflow event was always generated.

/proc/sys/fs/inotify/max_user_instances
This specifies a upper limit on the number of inotify instances so can be created per real user ID.

/proc/sys/fs/inotify/max_user_watches
This specifies a upper limit on the number of watches so can be created per real user ID.

If you are monitoring a large directory, then other restrictions you must also consider, call read, pay attention to return is a complete

struct Inotify_event {
int WD; /* Watch Descriptor */
uint32_t mask; /* Mask of events */
uint32_t cookies; /* Unique Cookie associating related
Events (for rename (2)) */
uint32_t Len; /* Size of Name field */
Char name[]; /* Optional null-terminated name */
};

Structure.

http://blog.csdn.net/myarrow/article/details/70964601. INotify main functions

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

As is known to all, Linux desktop systems and MAC or Windows in order to improve this situation, the open source community proposes that the kernel provide some mechanism for the user to know what is happening in the kernel or the underlying hardware, so that it can better manage the device and provide better services to users, such as HotPlug, Udev and INotify is what this demand has spawned. 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.

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, and the header file Linux each of the events represented is defined in the/inotify.h. 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_watch {        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; i<wD_num; wd= "Inotify_add_watch (FD," Add (event-if {len) < buffer)-*) Event (((char while *) buffer; inotify_event event len); Len= '%d.\n ', ' happens, printf (? Some offset= "buffer;" max_buf_size)) buffer, while (len= "read (FD,"} wd_array[i].wd= "WD;" Exit ( -1); wd_array[i].name); %s.\n?, for watch printf (? Can?t 0) (wd in_all_events); Wd_array[i].name, wd_array[i].name= "monitored_files[i"; i++) >mask & 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; }}


Transferred from: http://linux.chinaitlab.com/kernel/391147_4.html

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.