Debe introducir al menos 3 caracteres en el buscador.
Inicio / Wikis / Tutoriales / Dentro del núcleo Linux 2.4 - Colas de espera

Dentro del núcleo Linux 2.4 - Colas de espera

 ***-- (2 opiniones)
GNU Free Documentation License Tutorial de Tigran Aivazian - 14 de Febrero de 2006
Temas Relacionados: Linux
13. Colas de espera
Cuando un proceso solicita el núcleo para hacer algo que es actualmente imposible pero que quizás sea posible más tarde, el proceso es puesto a dormir y es despertado cuando la solicitud tiene más probabilidades de ser satisfecha. Uno de los mecanismos del núcleo usados para esto es llamado 'cola de espera'.

La implementación de Linux nos permite despertar usando la bandera TASK_EXCLUSIVE. Con las colas de espera, también puedes usar una cola bien conocida y entonces simplificar sleep_on/sleep_on_timeout/interruptible_sleep_on/interruptible_sleep_on_timeout, o puedes definir tu propia cola de espera y usar add/remove_wait_queue para añadir y quitarte desde ella y wake_up/wake_up_interruptible para despertar cuando se necesite.

Un ejemplo del primer uso de las colas de espera es la interacción entre el asignador de páginas (en mm/page_alloc.c:alloc_pages()) y el demonio del núcleo kswapd (en mm/vmscan.c:kswap()), por medio de la cola de espera kswapd_wait, declarada en mm/vmscan.c; el demonio kswapd duerme en esta cola, y es despertado cuando el asignador de páginas necesita liberar algunas páginas.

Un ejemplo del uso de una cola de espera autónoma es la interacción entre la solicitud de datos de un proceso de usuario a través de la llamada al sistema read(2) y el núcleo funcionando en el contexto de interrupción para suministrar los datos. Un manejador de interrupciones quizás se parezca a (drivers/char/rtc_interrupt() simplificado):



static DECLARE_WAIT_QUEUE_HEAD(rtc_wait);

void rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
spin_lock(&rtc_lock);
rtc_irq_data = CMOS_READ(RTC_INTR_FLAGS);
spin_unlock(&rtc_lock);
wake_up_interruptible(&rtc_wait);
}




Por lo tanto, el manejador de interrupciones obtiene los datos leyendo desde algún puerto de E/S específico del dispositivo (la macro CMOS_READ() devuelve un par de outb/inb) y entonces despierta a quien esté durmiendo en la cola de espera rtc_wait.

Ahora, la llamada al sistema read(2) puede ser implementada como:



ssize_t rtc_read(struct file file, char *buf, size_t count, loff_t *ppos)
{
DECLARE_WAITQUEUE(wait, current);
unsigned long data;
ssize_t retval;

add_wait_queue(&rtc_wait, &wait);
current->state = TASK_INTERRUPTIBLE;
do {
spin_lock_irq(&rtc_lock);
data = rtc_irq_data;
rtc_irq_data = 0;
spin_unlock_irq(&rtc_lock);

if (data != 0)
break;

if (file->f_flags & O_NONBLOCK) {
retval = -EAGAIN;
goto out;
}
if (signal_pending(current)) {
retval = -ERESTARTSYS;
goto out;
}
schedule();
} while(1);
retval = put_user(data, (unsigned long *)buf);
if (!retval)
retval = sizeof(unsigned long);

out:
current->state = TASK_RUNNING;
remove_wait_queue(&rtc_wait, &wait);
return retval;
}




Lo que pasa en rtc_read() es esto:

  1. Declaramos un elemento de la cola de espera apuntando al contexto del proceso actual.
  2. Añadimos este elemento a la cola de espera rtc_wait
  3. Marcamos el actual contexto como TASK_INTERRUPTIBLE lo que significa que no será replanificado después de la próxima vez que duerma.
  4. Chequeamos si no hay datos disponibles; si los hay empezamos, copiamos los datos a la memoria intermedia del usuario, nos marcamos como TASK_RUNNING, nos quitamos de la cola de espera y regresamos.
  5. Si todavía no hay datos, chequeamos cuando el usuario especificó una E/S no bloqueante, y si es así entonces fallamos con EAGAIN (el cual es el mismo que EWOULDBLOCK)
  6. También chequeamos si hay alguna señal pendiente y si por lo tanto informamos a las "capas superiores" para reinicializar la llamada al sistema si es necesario. Por "si es necesario" yo entiendo los detalles de la disposición de la señal tal como están especificadas en la llamada al sistema sigaction(2).
  7. Entonces "salimos", esto es, nos dormimos, hasta que sea despertado por el manejador de interrupciones. Si no nos marcamos como TASK_INTERRUPTIBLE entonces el planificador nos podrá planificar tan pronto como los datos estean disponibles, causando así procesamiento no necesario.

Es también valioso apuntar que, usando una cola de espera, es bastante más fácil implementar la llamada al sistema poll(2):



static unsigned int rtc_poll(struct file *file, poll_table *wait)
{
unsigned long l;

poll_wait(file, &rtc_wait, wait);

spin_lock_irq(&rtc_lock);
l = rtc_irq_data;
spin_unlock_irq(&rtc_lock);

if (l != 0)
return POLLIN | POLLRDNORM;
return 0;
}




Todo el trabajo es realizado por la función independiente del dispositivo poll_wait() la cual hace las manipulaciones necesarias en la lista de espera; todo lo que necesitamos hacer es apuntarla a la cola de espera la cual es despertada por nuestro manejador de interrupciones específico del dispositivo.
Autor y licencia de 'Dentro del núcleo Linux 2.4 - Colas de espera'
Tigran Aivazian Extraído de: http://es.tldp.org/Manuales-LuCAS/DENTRO-NUCLEO-LINUX/dentro-nucleo-linux-html/ GNU Free Documentation License
Licencia GNU Free Documentation License: http://www.es.gnu.org/licencias/fdles.html
Este contenido ha sido recopilado por el equipo de Wikilearning. Todo el contenido recopilado se ha obtenido respetando y comunicando en nuestro site la licencia de cada fuente.
Wikilearning tiene permiso expreso por escrito de los autores para publicar los contenidos que ha extraído de otras webs, incluyendo su uso comercial.

Wikis relacionados con 'Dentro del núcleo Linux 2.4 - Colas de espera'

Este documento describe cómo hacer el enmascarado (masqueradinq), proxy transparente, reenvío de puertos (port forwarding),... Más »
La fijación de precios está convirtiéndose en un modo de vida para muchos minoristas y... Más »
Este es el COMO Programar el puerto serie en Linux. Todo sobre cómo programar comunicaciones... Más »
En este documento se presenta la información acerca de la instalación, configuración, ejecución y mantenimiento... Más »
Esta es la primerísima edición del Linux en Castellano COMO. La audiencia a la que... Más »
¿Estás seguro de que deseas eliminar este capítulo?