Select function implementation principle analysis

  
 

select requires driver support, and the driver implements the poll function in fops. Select determines whether there are resources available (such as readable or writable) through the information provided by the poll function corresponding to each device file, and if so, returns the number of file descriptors of available resources. If not, sleeps, waiting for resources. When it becomes available, it is woken up and continues to execute.


The following is a two-process analysis of select:


1. The sleep process of select


< A device driver that supports blocking operations typically implements a set of its own wait queues, such as read/write wait queues, to support the BLOCK or NONBLOCK operations required by the upper layer (user layer). When the application accesses the device through the device driver (the default is BLOCK operation), if the device does not currently have data to read or write, the user process is inserted into the read/write wait queue corresponding to the device driver to let it sleep for a period of time. Wait until the data is readable/writable and then wake up the process.


select is a clever use of the wait queue mechanism to allow the user process to sleep properly when there is no resource to read/write, and to wake up when the resource is readable/writable. Let's take a look at the detailed process of select sleep.


select loops through the poll function of the driver corresponding to all file descriptors in the fd_set it monitors. The poll function provided by the driver first inserts the user process that calls select into the wait queue of the corresponding resource of the device driver (such as the read/write wait queue), and then returns a bitmask to tell the select which resources are available. When the select loop traverses the poll function corresponding to the file descriptor specified in all fd_sets, if no resource is available (that is, no file is available for operation), select causes the process to sleep, until the resource is available, the process is Wake up (or timeout) continues to execute.


The following is an analysis of how the code is implemented.

The calling path of select is as follows: sys_select -> core_sys_select -> do_select

The most important function is do_select, the main work is here, the first two functions mainly do some Ready to work. Do_select is defined as follows:

int do_select(int n, fd_set_bits *fds, s64 *timeout)

{

struct poll_wqueues table;

poll_table *wait ;

int retval, i;


rcu_read_lock();

retval = max_select_fd(n, fds);

rcu_read_unlock ();


if (retval < 0)

return retval;

n = retval;


poll_initwait(&table);

wait = &table.pt;

if (!*timeout)

wait = NULL;

retval = 0; //retval is used to save the number of prepared descriptors, initially 0

for (;;) {

unsigned long *rinp, *routp, * Rexp, *inp, *outp, *exp;

long __timeout;


set_current_state(TASK_INTERRUPTIBLE); //Change the current process state to TASK_INTERRUPTIBLE


inp = fds->in; outp = fds->out; exp = fds->ex;

rinp = fds->res_in; routp = fds- >res_out; rexp = fds->res_ex;


for (i = 0; i < n; ++rinp, ++routp, ++rexp) { //Traverse each descriptor

unsigned long in, out, ex, all_b Its, bit = 1, mask, j;

unsigned long res_in = 0, res_out = 0, res_ex = 0;

const struct file_operations *f_op = NULL;

Struct file *file = NULL;


in = *inp++; out = *outp++; ex = *exp++;

all_bits = in

Copyright © Windows knowledge All Rights Reserved