Article Title: Analysis of missing events in the event monitoring mechanism of Linux. 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.
Currently, Epoll + iNotify is commonly used to monitor File System Changes in Linux.
Epoll has two mechanisms: LevelTrigger and EdgeTrigger. The former is equivalent to fast poll, and the latter can be understood as blocking nonblocking fd. This statement is strictly amateur, this is just to illustrate the problem.
Wait for the event to be triggered from epoll_wait, and then read. here, we will explain that epoll in Linux is asynchronous reading while IOCP in Windows is synchronous reading. We can find that synchronous reading has more advantages.
At the beginning, the priority of the thread where the wait event occurs and read is not increased. It is found that when files and directories are added to the directory too frequently, the event will be lost. in this way, we need to find a way to compensate for the loss of events during real-time synchronization.
The first solution is to scan the newly added directory by first adding the directory add_watch. add_watch is only used to ensure that the new directory is added to watch. It is not missed unless the event is missed. omission refers to the period before the directory is created and reported to be added to watch. When another file or directory is created in the directory, the event is missed. iNotify allows two times of add_watch for the same directory, but because the hard disk needs to be accessed during the add operation to ensure that the directory exists before it can be added, a cache is provided, path <---> wd, use the path search to determine whether add_watch is enabled. If no add is enabled, add the following.
In the first solution, the problem of missed events is solved through post-event scanning, but does it make sense to scan it again? After analyzing the Linux thread finite level and scheduling policy, it is found that there are two real-time priorities: SCHED_FIFO and SCHED_RR. From Linux kernel development, chapter4 RealTime can be seen:
"SCHED_RR is identical to SCHED_FIFO packet t that each process can run only until it exhausts a predetermined timeslice. that is, SCHED_RR is SCHED_FIFO with timeslicesit is a real-time round-robin scheduling algorithm. when a SCHED_RR task exhausts its timeslice, any other real-time processes at its priority are scheduled round. the timeslice is used only to allow rescheduling of same-priority processes."
That is to say, if the read event thread is set to FIFO, there is no timeslice restriction. It can be done until the read event is read and won't be preemptible. RR is used after one timeslice is used up, it will be scheduled to other threads, and I think the FIFO setting can be used to replace inefficient scanning.
Note 1:
To set a thread policy, you can use the following api:
1. pthread_attr_getschedpolicy (const pthread_attr_t * restrict attr, int * restrict policy );
2. pthread_attr_setschedpolicy (pthread_attr_t * attr, int policy );
To set the thread priority, use the following api:
1. int sched_get_priority_max (int policy );
2. int sched_get_priority_min (int policy );
3. int pthread_attr_getschedparam (const pthread_attr_t * restrict attr,
4. struct sched_param * restrict param );
5. int pthread_attr_setschedparam (pthread_attr_t * restrict attr,
6. const struct sched_param * restrict param );
7. struct sched_param sched;
8. sched. sched_priority = sched_get_priority_max (SCHED_FIFO );
9. pthread_attr_setschedparam (attr, & sched );
The second solution is generated because when the first solution is implemented and multiple CPUs or cores are found, there are still missed reports, and there is no rule for missed reports, the number of files or directories is not fixed ,. after a variety of simulation tests, it is found that there is no problem with reading events under a single CPU. However, under multiple CPUs, the number of cores is allocated to the threads of reading events. at this time, we will find that the events we read are not general chaos, and there is no rule to follow. without any analysis, I assume that inotify will synchronize the reading of its internal RB-Tree, so I will read it with multiple threads for efficiency, when the result is in a multi-U state, the read is messy. after changing the read thread to one, there will be no missed events. However, considering the efficiency, we still need to use multiple threads to read the data. alternatively, you can lock the read of each thread to ensure that the buffer in iNotify is synchronized during read. the specific results will be verified tomorrow;
In this example, the iocp of Windows reads data synchronously, first reads data and then getiocpstatus. Epoll of Linux reads data asynchronously. I personally think it may be that ms has tested the asynchronous reading method, and finally selected the synchronous reading method, which saves a lot of effort for the write application. another point is that inotify does not include the parameters of the iterative monitoring sub-directory, but Windows has such considerations. This is also a comprehensive design of win.