Análisis de implementación de Poll &&epoll (1) —poll implementación

  

La cola de espera en el kernel de Linux tiene muchos usos para el manejo de interrupciones, sincronización de procesos y temporización. Aquí solo decimos que los procesos a menudo tienen que esperar a que ocurran ciertos eventos. Las colas de espera implementan esperas condicionales en eventos: los procesos que desean esperar un evento en particular se colocan en la cola de espera apropiada y renuncian al control. Por lo tanto, la cola de espera representa un conjunto de procesos de suspensión y, cuando se cumple una determinada condición, el núcleo los despierta.

La cola de espera se implementa mediante una lista enlazada circular que consta de un encabezado de cola de espera (wait_queue_head_t) y una entrada de cola de espera (wait_queue) cuyos elementos (elementos de la cola de espera) contienen punteros para procesar los descriptores. Cada cola de espera tiene una cabecera de cola de espera. La cabecera de la cola de espera es una estructura de datos del tipo wait_queue_head_t.
define el encabezado de la cola de espera (el contenido relevante se puede encontrar en linux /include /wait.h) Br>

Espere la definición de la estructura del encabezado de la cola:

struct wait_queue_head {

spinlock_t lock; //variable de bloqueo del giro, utilizada en el encabezado de la cola de espera

struct list_head task_list; //list_head

} a la cola de espera;

typedef struct __wait_queue_head wait_queue_head_t;

Al usar la cola de espera, primero debe definir un wait_queue_head, que se puede pasar La macro DECLARE_WAIT_QUEUE_HEAD está terminada, este es un método estáticamente definido. Esta macro define un wait_queue_head e inicializa los bloqueos en la estructura, así como la cola de espera.


La idea de las colas de espera en Linux es la que se muestra en la siguiente figura. Cuando una tarea debe suspenderse en un wait_queue_head, encapsula su propia información de bloque de control de procesos en wait_queue y luego se cuelga. Cargado en la lista enlazada de wait_queue, realiza el sueño programado. Cuando ocurren ciertos eventos, otra tarea (proceso) despierta una o todas las tareas en wait_queue_head. El trabajo de activación establece las tareas en la cola de espera en un estado programable y las elimina de la cola.



(2) Esperando que la cola almacene el proceso que no se puede obtener cuando se realiza la operación del dispositivo.

Definición de la columna de espera :

struct wait_queue {

unsigned int flags; //prepare_to_wait () tiene operaciones en flags, vea para obtener el significado de

#define WQ_FLAG_EXCLUSIVE 0x01 //Una constante, en prepare_to_wait (), utilizada para modificar el valor de las banderas

void * private //generalmente apunta al bloque de control de la tarea actual

wait_queue_func_t func; //wake up la función de la tarea de bloqueo, determina la activación

struct list_head task_list; //Lista de tareas de bloqueo

};

typedef struct __wait_queue wait_queue_t;



análisis de implementación de sondeo

1.select/poll desventajas

Las desventajas de seleccionar /son: 1. Lea los parámetros desde el modo de usuario varias veces cada vez que llame. 2. El descriptor de archivo se escanea repetidamente cada vez que se llama. 3. Cada vez que se inicia la llamada, el proceso actual se coloca en la cola de espera para cada descriptor de archivo. Una vez que finaliza la llamada, el proceso se elimina de cada cola de espera.

2. Implementación del Kernel

2.1 Estructura de datos principal:
(1) struct poll_table_entry {

struct file filp;

wait_queue_t Espera; //internamente tiene un puntero a un proceso

wait_queue_head_t wait_address; //espera el encabezado de la cola (la cola de espera tiene múltiples wait_queue_t compuestas, conectadas a través de una lista de doble enlace)

};
(2) struct poll_table_page {

struct poll_table_page next;

struct poll_table_entry entry;

struct poll_table_entry entry [0];

};
(3) struct poll_wqueues {

poll_table pt; //un puntero a función, que generalmente apunta a __pollwait o nulo

struct poll_table_page * table;

int error;

};
(4) struct poll_list {

struct poll_list * next; //Conectar por página de memoria, porque kmalloc tiene restricciones de datos de aplicación

int len; //La cantidad de fd pasados ​​al espacio de usuario

struct pollfd entries [0]; //Almacena los datos almacenados en el espacio de usuario

};

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

2,2 sondeo función de llamada al sistema del total figura

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

Copyright © Conocimiento de Windows All Rights Reserved