Arm basics: Poll mechanism analysis (to Wei Dongshan)

Source: Internet
Author: User

I recently read the implementation of the Linux Poll mechanism and the analysis documents of instructor Wei, which are summarized as follows:

Int poll (struct pollfd * fds, nfds_t nfds, int timeout );

In general, the Poll mechanism will determine whether the files in fds are readable. If the files are readable, the system will return immediately. The returned value is the number of readable fd. If the files are unreadable, then the process will sleep for such a long time as timeout, and then judge whether there is any file readable. If yes, the number of fd is returned. If no, 0 is returned.

In the kernel, the implementation process is roughly as follows:

When the application calls the poll function, the system calls the sys_poll function. This function finally calls the do_poll function. The do_poll function has an endless loop, the do_pollfd function will be used to call the poll function in the driver (the character driver of each member in the fds will be scanned). There are two Poll functions in the driver, one is to call the poll_wait function and mount the process to the waiting queue (this is required. To sleep, you must be in a waiting queue, otherwise, where can I wake you up ??), The other is to determine whether the related fd has the readable content. If it is readable, 1 is returned; otherwise, 0 is returned. If it returns 1, the count ++ in the do_poll function, then, the do_poll function judges the three conditions (if (count |! Timeout | signal_pending (current) jumps out directly if it is set up. If it is not set up, sleep timeout jiffes for such a long time (calling schedule_timeout for sleep ), if no other process wakes up during this period, the second execution will jump out of the endless loop. If other processes wake it up during this period, they can also jump out of the endless loop (for example, we can use the interrupt handler function to wake it up, so that data can be read, ).

 

 

Poll Mechanism Analysis

Wei Dongshan 2009.12.10

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.

1. The sys_poll function is located in the fs/select. c file. The Code is as follows:

asmlinkagelong sys_poll(struct pollfd __user *ufds, unsigned int nfds, long timeout_msecs){         s64 timeout_jiffies;         if (timeout_msecs > 0) {#ifHZ > 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 processing the timeout parameter.

 

2. 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.

 

 

3. 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 ){...... For (;;){...... If (do_pollfd (pfd, pt) {count ++; pt = NULL ;}...... If (count |! * Timeout | signal_pending (current) {break;} count = wait-> error; if (count) break; if (* timeout <0) {/* Wait indefinitely */_ timeout = MAX_SCHEDULE_TIMEOUT;} else if (unlikely (* timeout> = (s64) MAX_SCHEDULE_TIMEOUT-1) {/** Wait for longer than MAX_SCHEDULE_TIMEOUT. do it in * a loop */_ timeout = MAX_SCHEDULE_TIMEOUT-1; * timeout-= _ timeout;} else {_ timeout = * timeout; * timeout = 0 ;} _ timeout = schedule_timeout (_ timeout); // The sleep time is provided by the application if (* timeout> = 0) * timeout + = _ timeout ;} _ set_current_state (TASK_RUNNING); returncount ;}

 

By analyzing the code, you can find that its function is as follows:

① You can see from row 02 that this is a loop and its exit condition is:

A. One of the three conditions of row 09 (count is not 0, timeout, signal waiting for processing)

Count Plus 0 indicates that the do_pollfd of row 04 has at least one success.

B. 11 and 12 rows: Error

② Focus on the do_pollfd function, which will be further 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.

 

4. The do_pollfd function is located in the fs/select. c file. The Code is as follows:

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);……}

 

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:

staticinline 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. 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:

staticvoid __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 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 use poll_wait, our program has the opportunity to be awakened: chedule_timeout (_ timeout), just sleep _ 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 do_sys_poll will sleep the process for a certain period of time. This time is the "timeout time" provided by the application"

 

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 action repeats Step 2 and Step 3 until the input time of the poll call of the application is reached, then return.

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.