Poll Mechanism analysis
Vedon 2009.12.10
All system calls, based on the "Sys_" prefix in front of its name, are the corresponding functions in the kernel. For example, the system calls open, read, write, poll, and the corresponding kernel functions are: Sys_open, Sys_read, Sys_write, Sys_poll.
First, the kernel framework:
For system calls poll or select, their corresponding kernel functions are sys_poll. The poll mechanism can be understood by analyzing sys_poll.
- The Sys_poll function is located in the Fs/select.c file with the following code:
Asmlinkage long Sys_poll (struct POLLFD __user *ufds, unsigned int Nfds,
Long Timeout_msecs)
{
S64 timeout_jiffies;
if (Timeout_msecs > 0) {
#if HZ > 1000
/* We can only overflow if HZ > 1000 */
if (timeout_msecs/1000 > (S64) 0x7fffffffffffffffull/(S64) HZ)
Timeout_jiffies =-1;
Else
#endif
Timeout_jiffies = Msecs_to_jiffies (timeout_msecs);
} else {
/* Infinite (< 0) or no (0) Timeout */
Timeout_jiffies = Timeout_msecs;
}
Return Do_sys_poll (UFDs, Nfds, &timeout_jiffies);
}
It calls Do_sys_poll directly after the timeout parameter has been slightly processed.
- The Do_sys_poll function is also located in the Fs/select.c file, and we ignore the other code:
int Do_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 with the following code:
static int do_poll (unsigned int nfds, struct poll_list *list,
struct Poll_wqueues *wait, S64 *timeout)
{
01 ...
(;;) {
03 ...
if (DO_POLLFD (PFD, PT)) {
count++;
PT = NULL;
07}
08 ...
if (count | |!*timeout | | signal_pending (current))
Ten break;
Count = wait->error;
if (count)
break;
14
if (*timeout < 0) {
*/* Wait indefinitely */
__timeout = Max_schedule_timeout;
* Else if (unlikely (*timeout >= (S64) max_schedule_timeout-1)) {
19/*
* Wait for longer than Max_schedule_timeout. Do it in
* a loop
22 */
__timeout = max_schedule_timeout-1;
*timeout-= __timeout;
-} else {
__timeout = *timeout;
*timeout = 0;
28}
29
__timeout = Schedule_timeout (__timeout);
if (*timeout >= 0)
*timeout + = __timeout;
33}
__set_current_state (task_running);
return count;
36}
By analyzing the code, you can see that it works as follows:
① from 02 lines can be known, this is a loop, it exits the condition is:
- One of the 3 conditions of line 09 (count not 0, timed out, signaled waiting to be processed)
Count non 0 indicates that a DO_POLLFD of 04 rows has at least one success.
- 11, 12 lines: Error occurred
② focus on the DO_POLLFD function, followed by analysis
③ Line 30th, 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 goes into hibernation. So, who wakes up? In addition to hibernation to a specified time by the system wake up, can also be awakened by the driver--remember this, this is why the driver of the poll to call Poll_wait, the reason behind the analysis.
- The DO_POLLFD function is located in the Fs/select.c file with the following code:
static inline unsigned int do_pollfd (struct POLLFD *pollfd, poll_table *pwait)
{
......
if (file->f_op && file->f_op->poll)
Mask = file->f_op->poll (file, pwait);
......
}
Visible, it is the poll function that is registered in the call to our driver.
Second, the driver:
There are two places in the driver that are related to poll: One is to define your own poll function when constructing the file_operation structure. The second is to invoke the __pollwait function mentioned above through poll_wait, pollwait code is as follows:
static inline void 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, which, from its code, simply hangs the current process into a queue defined in our driver. Its code is as follows:
static void __pollwait (struct file *filp, wait_queue_head_t *wait_address,
Poll_table *p)
{
struct Poll_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 executing to the driver's poll_wait function, the process does not hibernate, and the poll function implemented in our driver does not cause hibernation. Let the process go into hibernation, which is the 30 line "__timeout = Schedule_timeout (__timeout)" of the previously parsed do_sys_poll function.
Poll_wait just hangs the process into a queue, application calls poll > Sys_poll > Do_sys_poll > Poll_initwait,do_poll > Do_pollfd > We write our own poll function, and then call Schedule_timeout into hibernation. If our driver discovers the situation is ready, we can wake up the process that hangs on this queue. As you can see, poll_wait's role is just to let the driver find the process to wake up. Even without poll_wait, our program has the opportunity to be awakened: Chedule_timeout (__timeout), just to hibernate __time_out this time.
Now to summarize the poll mechanism:
1. Poll > Sys_poll > Do_sys_poll > Poll_initwait,poll_initwait function Register the callback function __pollwait, it is when our driver executes poll_wait, The function that is actually called.
2. Next execute File->f_op->poll, which is the poll function implemented in our driver
It calls Poll_wait to hang itself into a queue, which is also defined by our driver;
It also determines if the device is ready.
3. If the device is not ready, Do_sys_poll will let the process sleep for a certain time
4. The process is awakened by a condition of 2: one is "a certain time" mentioned above, and the second is awakened by the driver. When the driver discovers that the condition is ready, it wakes up the process that hangs on "one queue", which is the queue in front of which the process was hung past poll_wait.
5. If the driver does not go to wake the process, then Chedule_timeout (__timeou) times out, 2, 3 actions are repeated until the poll call of the application arrives at the incoming time.
Analysis of poll mechanism of Linux communication