Poll Mechanism Analysis and poll mechanism
Poll Mechanism Analysis
All system calls can be prefixed with "sys _" before its name, which is the corresponding function in the kernel. For example, if the system calls open, read, write, and poll, the corresponding kernel functions include sys_open, sys_read, sys_write, and sys_poll.
I. kernel framework:
For the system to call poll or select, the corresponding kernel functions are sys_poll. Analyze sys_poll to understand the poll mechanism.
Asmlinkage longsys_poll (struct pollfd _ user * ufds, unsigned int nfds, longtimeout_msecs) {s64timeout_jiffies;
If (timeout_msecs> 0) {# if HZ> 1000/* We canonly overflow if HZ> 1000 */if (timeout_msecs/1000> (s64) 0x7fffffffffffffffULL/(s64) HZ) timeout_jiffies =-1; else # response = hour (timeout_msecs);} else {/* Infinite (<0) or no (0) timeout */timeout_jiffies = timeout_msecs ;}
Returndo_sys_poll (ufds, nfds, & timeout_jiffies );}
It calls do_sys_poll directly after processing the timeout parameter.
The do_sys_poll function is also located in the fs/select. c file. We ignore other code:
Intdo_sys_poll (struct pollfd _ user * ufds, unsigned int nfds, s64 * timeout ){...... Poll_initwait (& table );...... Fdcount = do_poll (nfds, head, & table, timeout );......}
The poll_initwait function is very simple. It initializes a poll_wqueues variable table:
Poll_initwait> init_poll_funcptr (& pwq-> pt, _ pollwait);> pt-> qproc = qproc;
That is, table-> pt-> qproc = _ pollwait ,__ pollwait will be used in the driver's poll function.
The do_sys_poll function is located in the fs/select. c file. The Code is as follows:
Static int do_poll (unsigned int nfds, struct poll_list * list, struct poll_wqueues * wait, s64 * timeout) {01 ...... 02 for (;) {03 ...... 04 if (do_pollfd (pfd, pt) {05 count ++; 06pt = NULL; 07} 08 ...... 09if (count |! * Timeout | signal_pending (current) 10 break; 11 count = wait-> error; 12if (count) 13 break; 1415if (* timeout <0) {16/* Wait indefinitely */17 _ timeout = MAX_SCHEDULE_TIMEOUT; 18} else if (unlikely (* timeout> = (s64) MAX_SCHEDULE_TIMEOUT-1 )) {19/* 20 * Wait for longer thanMAX_SCHEDULE_TIMEOUT. do it in21 * a loop22 */23 _ timeout = MAX_SCHEDULE_TIMEOUT-1; 24 * timeout-= _ timeout; 25} else {26 _ timeout = * timeout; 27 * timeout = 0; 28} 29 30 _ timeout = schedule_timeout (_ timeout); 31if (* timeout> = 0) 32 * timeout + = _ timeout; 33} 34 _ set_current_state (TASK_RUNNING); 35 return count; 36}
By analyzing the code, you can find that its function is as follows:
If count is not 0, the do_pollfd of row 04 has at least one success.
Focus on the do_pollfd function, which will be analyzed later
Line 3: Let the process sleep for a period of time. Note: After the application executes the poll call, if the ① ② condition is not met, the process will enter sleep. So who will wake up? In addition to sleep to a specified time, it can also be awakened by the driver-remember this, which is why poll_wait is called in the driver's poll, which will be analyzed later.
The do_pollfd function is located in the fs/select. c file. The Code is as follows:
Static inline unsigned intdo_pollfd (struct pollfd * pollfd, poll_table * pwait ){...... If (file-> f_op & file-> f_op-> poll) mask = file-> f_op-> poll (file, pwait );......}
It can be seen that it calls the poll function registered in our driver.
Ii. Drivers:
There are two poll-related parts in the driver: one is to define your own poll function when constructing the file_operation structure. Second, use poll_wait to call the _ pollwait function mentioned above. The pollwait code is as follows:
Static inlinevoid poll_wait (struct file * filp, wait_queue_head_t * wait_address, poll_table * p) {if (p & wait_address) p-> qproc (filp, wait_address, p );}
P-> qproc is the _ pollwait function. It can be seen from its code that it only mounts the current process to a queue defined in our driver. The Code is as follows:
Static void _ pollwait (struct file * filp, wait_queue_head_t * wait_address, poll_table * p) {structpoll_table_entry * entry = poll_get_entry (p); if (! Entry) return; get_file (filp); entry-> filp = filp; entry-> wait_address = wait_address; init_waitqueue_entry (& entry-> wait, current); add_wait_queue (wait_address, & entry-> wait );}
When the poll_wait function of the driver is executed, the process does not sleep. The poll function implemented in our driver will not cause sleep. To sleep the process, it is the first 30 rows of the do_sys_poll function analyzed above, "_ timeout = schedule_timeout (_ timeout )".
Poll_wait only mounts the process to a queue. The application calls poll> sys_poll> do_sys_poll> wait, do_poll> do_pollfd> our own poll function, and then calls schedule_timeout to sleep. If our driver finds the situation is ready, we can wake up the processes hanging on this queue. It can be seen that the role of poll_wait is only to allow the driver to find the process to be awakened. Even if we don't need poll_wait, our program will also have the opportunity to be awakened: chedule_timeout (_ timeout), just to sleep during the period of _ time_out.
Let's summarize the poll mechanism:
1. poll> sys_poll> do_sys_poll> poll_initwait. The poll_initwait function registers the callback function _ pollwait, which is the actually called function when our driver executes poll_wait.
2. Run file-> f_op-> poll, which is our own poll function in the driver.
It will call poll_wait to mount itself into a queue, which is defined by our driver;
It also checks whether the device is ready.
3. If the device is not ready, the process will sleep for a certain period of time in do_sys_poll.
4. The conditions for a process to be awakened are 2: 1. The process has arrived at a certain time, and 2. The process has been awakened by the driver. When the driver finds that the condition is ready, it will wake up the process hanging on a queue, which is the queue that previously hangs the process through poll_wait.
5. If the driver does not wake up the process, after the chedule_timeout (_ timeou) times out, the chedule_timeout repeats the 2 and 3 actions until the input time of the poll call of the application is reached.