Poll&&epoll implementation analysis (a) - poll implementation

  
 

The wait queue in the Linux kernel has many uses for interrupt handling, process synchronization, and timing. We only say here that processes often have to wait for certain events to occur. Waiting queues implement conditional waits on events: Processes that want to wait for a particular event put themselves in the appropriate wait queue and give up control. Therefore, the wait queue represents a set of sleep processes, and when a certain condition is true, they are woken up by the kernel.

The wait queue is implemented by a circular list, consisting of a wait queue header (wait_queue_head_t) and a wait queue entry (wait_queue) whose elements (wait queue items) contain pointers to process descriptors. Each wait queue has a wait queue head. The wait queue header is a data structure of type wait_queue_head_t.
defines the wait queue header (the relevant content can be found in linux/include/wait.h) Br>

Wait for the definition of the queue header structure:

struct wait_queue_head {

spinlock_t lock; //spin lock variable, used in the wait queue header

struct list_head task_list; //list_head

} pointing to the wait queue;

typedef struct __wait_queue_head wait_queue_head_t;

When using the wait queue, you first need to define a wait_queue_head, which can be passed The DECLARE_WAIT_QUEUE_HEAD macro is done, this is a statically defined method. This macro defines a wait_queue_head and initializes the locks in the structure as well as the wait queue.


The idea of ​​waiting queues in Linux is as shown in the following figure. When a task needs to sleep on a wait_queue_head, it encapsulates its own process control block information into wait_queue, and then hangs Loaded into the linked list of wait_queue, performs scheduled sleep. When certain events occur, another task (process) wakes up one or all of the tasks on wait_queue_head. Wake-up work sets the tasks in the wait queue to a schedulable state and removes them from the queue.



(2) Waiting for the queue to store the process that cannot be obtained when the device operation is performed.

Defining the waiting column :

struct wait_queue {

unsigned int flags; //prepare_to_wait() has operations on flags, see to get the meaning

#define WQ_FLAG_EXCLUSIVE 0x01 //A constant, in prepare_to_wait () used to modify the value of flags

void * private //usually point to the current task control block

wait_queue_func_t func; //wake up the function of the blocking task, decided to wake up

struct list_head task_list; //Blocking task list

};

typedef struct __wait_queue wait_queue_t;



poll implementation analysis

1.select/poll disadvantages

The disadvantages of select/poll are: 1. Read parameters from the user mode repeatedly each time you call. 2. The file descriptor is scanned repeatedly every time it is called. 3. Each time the call starts, the current process is placed in the wait queue for each file descriptor. After the call ends, the process is removed from each wait queue.

2. Kernel Implementation

2.1 Main Data Structure:
(1) struct poll_table_entry {

struct file filp;

wait_queue_t Wait; //internally has a pointer to a process

wait_queue_head_t wait_address; //wait for the queue header (waiting queue has multiple wait_queue_t composed, connected through a double-linked list)

};
(2) struct poll_table_page {

struct poll_table_page next;

struct poll_table_entry entry;

struct poll_table_entry entries[0];

};
(3) struct poll_wqueues {

poll_table pt;//a function pointer, usually pointing to __pollwait or null

struct poll_table_page * table;

int error;

};
(4) struct poll_list {

struct poll_list *next;//by memory page connection, because kmalloc has application data restrictions

int len;//User space incoming fd number

struct pollfd entries[0];//Store user space data

};

typedef void (*pol l_queue_proc) (struct file *, wait_queue_head_t *, struct poll_table_struct *); typedef struct poll_table struct {poll_queue_proc qproc;} poll_table;

2.2 poll system call function of the total FIG

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

Copyright © Windows knowledge All Rights Reserved