07-1-sincronizacion

7
Estudio de un S.O. Sincronización. Colas de espera. Juan-Carlos Perez-Cortes

Upload: kiring84

Post on 19-Nov-2015

3 views

Category:

Documents


1 download

DESCRIPTION

tema asignatura eso

TRANSCRIPT

  • Estudio de un S.O. Sincronizacin. Colas de espera. JuanCarlos PerezCortes

  • Table of Contents

    Tema 7. Sincronizacin......................................................................................................................................17.1 Introduccin.......................................................................................................................................17.2 Colas de espera: estructuras de datos.................................................................................................17.3 Insercin en las colas de espera.........................................................................................................27.4 Consultando y eliminando elementos de la cola de espera................................................................27.5 Durmiendo un proceso.......................................................................................................................37.6 Despertando un proceso.....................................................................................................................37.7 Cola de procesos en ejecucin...........................................................................................................4

    Estudio de un S.O. Sincronizacin. Colas de espera.

    i

  • Tema 7. Sincronizacin

    Colas de espera Juan Carlos Prez y Sergio Sez

    Juan Carlos PrezSergio Sez

    [email protected]@disca.upv.es

    7.1 Introduccin

    En algunas ocasiones, un proceso debe esperar la llegada de algn tipo de evento (llegada de datosdel disco, se ha pulsado una tecla, etc.). En estas ocasiones, el proceso deber abandonar la CPU yesperar la llegada de dicho evento (las espera activa no es una buena opcin en un sistemamultitarea).

    En Linux, los procesos que estm esperando algn tipo de evento lo hacen en una cola de espera.Hay una cola de espera por cada posible evento, v.g., todos los procesos que estn esperando que sepulse una tecla estn esperando en la misma cola.

    Las colas de espera contienen la informacin necesaria para localizar un proceso y volverlo a poneren la cola de ejecucin, junto al resto de los procesos preparados, una vez se haya producido elevento oportuno.

    7.2 Colas de espera: estructuras de datos

    Las colas de espera tienen dos estructuras de datos bsicas: los elementos de la cola y la cabeza de la cola deespera.

    Los elementos que se almacenan en una cola de espera del tipo wait_queue_t[include/linux/wait.h#L31].Los campos que contiene son: un campo de flags, un puntero task a la estructura que representaal proceso que est esperando ( La estructura task_struct representa una entrada en la TABLADE PROCESOS, donde se guarda toda la informacin relacionada con cada proceso ) y un campotask_list de tipo list_head para construir la cola de espera. Esta estructura tiene varioscampos opcionales para su depuracin que no se van a analizar.

    Un elemento de la cola de espera puede declararse e inicialziarse con la macroDECLARE_WAITQUEUE(name,tsk)[include/linux/wait.h#L139], o inicialziarse con la funcininit_waitqueue_entry().[include/linux/wait.h#L169]

    Los campos para la gestin de la cola no estn en la propia estructura task_struct para permitirque un proceso pueda esperar varios eventos.

    La cabeza de la cola es una estructura del tipo wait_queue_head_t[include/linux/wait.h#L77]. Tienedos nicos campos: el cerrojo lock para la manipulacin de la cola en exclusin mutua y el campotask_list de tipo list_head que es la cabeza de la cola de espera propiamente dicha.

    La cabeza de la cola de espera puede declararse e inicialziarse con la macro

    Tema 7. Sincronizacin 1

    mailto:[email protected]:[email protected]://bernia.disca.upv.es/lxr/http/source/include/linux/wait.h#L31http://bernia.disca.upv.es/lxr/http/source/include/linux/wait.h#L139http://bernia.disca.upv.es/lxr/http/source/include/linux/wait.h#L169http://bernia.disca.upv.es/lxr/http/source/include/linux/wait.h#L77

  • DECLARE_WAIT_QUEUE_HEAD(name,tsk)[include/linux/wait.h#L147], o inicialziarse con la funcininit_waitqueue_head().[include/linux/wait.h#L155]

    Resulta curioso observar en las estructuras de datos, y en el cdigo que se estudiar a continuacin, que lascolas de espera utilizan una arquitectura dual para la implementacin de los cerrojos. Los cerrojos utilizadospueden ser de tipo spin_lock, ms eficientes, o cerrojos de lectura/escritura de tipo rwlock_t, quepermiten una mayor concurrencia de lectores. Se pueden observar las definiciones en el ficherowait.h[include/linux/wait.h#L43].

    7.3 Insercin en las colas de espera

    Existen dos modos de insercin en una cola de espera: exclusivo y no exclusivo, relacionadosfundamentalmente con el cdigo que despierta a un proceso. Las funciones utilizadas son:

    La funcin add_wait_queue(q, wait)[kernel/fork.c#L39] aade la entrada wait en la cabeza dela cola de espera q en modo no exclusivo. Esta funcin deactiva el flag que indica "elementoexclusivo", adquiere el cerrojo de la cola q>lock y posteriormente invoca a la funcin__add_wait_queue()[include/linux/wait.h#L193], que es la que finalmente realiza la insercin. Paraello utiliza la funcin list_add() con el campo task_list.

    La funcin add_wait_queue_exclusive(q, wait)[kernel/fork.c#L49] aade la entrada wait alfinal de la cola de espera q en modo exclusivo. Esta funcin establece el flag como un elementoexclusivo, adquiere el cerrojo de la cola q>lock y finalmente invoca a la funcin__add_wait_queue_tail()[include/linux/wait.h#L209] que es la que realiza la insercin al final de lacola. Para ello utiliza la funcin list_add_tail() con el campo task_list.

    7.4 Consultando y eliminando elementos de la cola deespera

    Eliminar un elemento de una lista de espera es una operacin muy sencilla. Simplemente hay que invocar lafuncin remove_wait_queue(q, wait).[kernel/fork.c#L59]

    Dicha funcin elimina la entrada wait de la cola de espera q. Para ello simplemente adquiere elcerrojo q>lock , e invoca a la funcin __remove_wait_queue()[include/linux/wait.h#L223], que esla que finalmente elimina la entrada de la cola. Para ello utiliza la funcin list_del() sobre elcampo old>task_list.

    Para consultar si una cola de espera esta activa (con algn elemento) se utiliza la funcinwaitqueue_active(q)[include/linux/wait.h#L182]

    La funcin waitqueue_active(q) simplemente consulta que la cola q no este vacia con lafuncin list_empty() sobre el campo q>task_list.

    Estudio de un S.O. Sincronizacin. Colas de espera.

    7.3 Insercin en las colas de espera 2

    http://bernia.disca.upv.es/lxr/http/source/include/linux/wait.h#L147http://bernia.disca.upv.es/lxr/http/source/include/linux/wait.h#L155http://bernia.disca.upv.es/lxr/http/source/include/linux/wait.h#L43http://bernia.disca.upv.es/lxr/http/source/kernel/fork.c#L39http://bernia.disca.upv.es/lxr/http/source/kernel/fork.c#L39http://bernia.disca.upv.es/lxr/http/source/include/linux/wait.h#L193http://bernia.disca.upv.es/lxr/http/source/kernel/fork.c#L49http://bernia.disca.upv.es/lxr/http/source/kernel/fork.c#L49http://bernia.disca.upv.es/lxr/http/source/include/linux/wait.h#L209http://bernia.disca.upv.es/lxr/http/source/kernel/fork.c#L59http://bernia.disca.upv.es/lxr/http/source/kernel/fork.c#L59http://bernia.disca.upv.es/lxr/http/source/include/linux/wait.h#L223http://bernia.disca.upv.es/lxr/http/source/include/linux/wait.h#L182

  • 7.5 Durmiendo un proceso

    Meter la informacin relativa a un proceso en una cola de espera no hace que dicho proceso deje laCPU. Para que un proceso abandone la CPU deber pasar a estado no preparado y conseguir que seinvoque el planificador para que ste le quite la CPU.

    Simplificando, los estados en los que puede estar un proceso en Linux son tres:

    TASK_RUNNING: Aglutina los estados clsicos preparado y en ejecucin. En Linux no serealiza dicha distincin a nivel de estado del proceso. Este estado indica que dicho proceso escandidato para obtener una CPU en el planificador (si no la tiene ya, por supuesto).

    TASK_INTERRUPTIBLE: Coincide con el estado suspendido, pero le indica al sistema quepuede ser por un largo periodo de tiempo y que, por lo tanto, se le puede interrumpir si pasaalgo importante. Bsicamente dicho proceso puede recibir seales, lo que complica bastanteel cdigo.

    TASK_UNINTERRUPTIBLE: Coincide con el estado suspendido y, en este caso, no se lepuede interrumpir.

    Existen mltiples funciones para dormi un proceso, dependiendo del estado en el que se quiera dormir, etc.Todas las funciones son variantes de la funcin sleep_on(q)[kernel/sched.c#L829]. Las partes de dicha funcinson las siguientes:

    SLEEP_ON_VAR[kernel/sched.c#L790], que declara las variables necesarias para insertar el proceso actualen la cola de espera q, incluyendo la inicializacin de las estructura wait. [#831]

    Cambia el estado del proceso actual a TASK_UNINTERRUPTIBLE (suspendido sin posibilidad derecibir seales).[#833]

    SLEEP_ON_HEAD[kernel/sched.c#L795], inserta el proceso actual en la cola de espera q. [#835] Invoca al planificador, schedule(), para que se escoja a otro proceso para su ejecucin. La

    llamada a la funcin schedule()NO RETORNAR hasta que vuelva a ponerse en ejecucin elproceso actual. [#836]

    SLEEP_ON_TAIL[kernel/sched.c#L800], elimina al proceso actual de la cola de espera q. [#837]

    7.6 Despertando un proceso

    Al igual que con la funcin sleep_on(), existen muchas variantes a la hora de despertar a los procesos queestn en una cola de espera.

    El mecanismo bsico es la macro wake_up(q)[include/linux/sched.h#L595], que despierta a todos losprocesos no exclusivos de la cola q y como mximo a uno de los insertados en modo exclusivo.

    La macro wake_up_sync(q)[include/linux/sched.h#L598] es idntica a la anterior, pero indicando queadems el proceso que se depierta debe ejecutarse en la CPU que lo ha despertado.

    Las variantes con sufijo _nr y _all indican que se debe despertar a nr de los procesos que hay enmodo exclusivo o a todos respectivamente.

    Las variantes con sufijo _interruptible indican que slo hay que despertar a los procesos queestn en modo TASK_INTERRUPTIBLE.

    Estudio de un S.O. Sincronizacin. Colas de espera.

    7.5 Durmiendo un proceso 3

    http://bernia.disca.upv.es/lxr/http/source/kernel/sched.c#L829http://bernia.disca.upv.es/lxr/http/source/kernel/sched.c#L790http://bernia.disca.upv.es/lxr/http/source/kernel/sched.c#L795http://bernia.disca.upv.es/lxr/http/source/kernel/sched.c#L800http://bernia.disca.upv.es/lxr/http/source/include/linux/sched.h#L595http://bernia.disca.upv.es/lxr/http/source/include/linux/sched.h#L598

  • Las macros wake_up y wake_up_sync acaban invocando a las funciones __wake_up(q, mode,nr)[kernel/sched.c#L740] y __wake_up_sync(q, mode, nr)[kernel/sched.c#L750] respectivamente, y ambasinvocan a __wake_up_common(q, mode, nr, sync)[kernel/sched.c#L707] tras comprobar que la lista noest vacia y adquirir el cerrojo correspondiente. La funcin __wake_up_common() realiza las siguientesacciones:

    Recorre todos los procesos que hay en la cola de espera. [#725] Obtiene el puntero al elemento actual de la cola y lo pone en la variable curr. [#725] Obtiene el estado del proceso actual. [#7301] Comprueba que el estado es uno de los permitidos para despertarlo. [#732] ...

    Se despertarn procesos de la cola hasta que uno de ellos cumpla:

    La funcin try_to_wake_up(p, sync)[kernel/sched.c#L343]

    pone el proceso en estado TASK_RUNNING[#360] comprueba que no est en la lista de ejecucin. Si ya est, sale y devuelve FALSE

    (0). [#3612] lo aade a la cola de ejecucin [#363], comprueba si se debe o no se puede ejecutar el

    proceso en la CPU actual [#364]. Si no se puede/debe ejecutar el proceso en esta CPUse intenta planificar en otra CPU, utilizando la funcinreschedule_idle()[kernel/sched.c#L212][#365]En el caso uniprocesador, la funcinreschedule_idle() comprueba si el proceso que se acaba de despertar tienems prioridad que el proceso que lo ha despertado (utilizando la funcinpreemption_goodness[kernel/sched.c#L200]), en cuyo caso marca el procesos actualcomo que se necesita replanificar.. Y finalmente devuelve TRUE.

    Comprueba si el proceso est en modo exclusivo. Si todava no se ha superado el lmite mximo de procesos en modo exclusivo que se deben

    despertar.

    7.7 Cola de procesos en ejecucin

    La manipulacin de la lista de procesos en ejecucin (estado TASK_RUNNING) es muy sencilla, pues se basaen la implementacin de listas doblemente enlazadas del ncleo.

    Cada proceso del sistema est representado por una estructura del tipo structtask_struct[include/linux/sched.h#L281].

    La estructura task_struct tiene un campo run_list[include/linux/sched.h#L321] del tipolist_head que sirve para enlazar todos los procesos que estn en estado TASK_RUNNING.

    Dicha cola se denomina runqueue, y se manipula con unas pocas funciones:add_to_runqueue()[kernel/sched.c#L318] , move_last_runqueue()[kernel/sched.c#L331],move_first_runqueue()[kernel/sched.c#L337] , del_from_runqueue()[include/linux/sched.h#L876] ytask_on_runqueue()[include/linux/sched.h#L884].

    add_to_runqueue(p)[kernel/sched.c#L318]: Aade el proceso p a la cola de ejecucin e incrementa

    Estudio de un S.O. Sincronizacin. Colas de espera.

    7.7 Cola de procesos en ejecucin 4

    http://bernia.disca.upv.es/lxr/http/source/kernel/sched.c#L740http://bernia.disca.upv.es/lxr/http/source/kernel/sched.c#L740http://bernia.disca.upv.es/lxr/http/source/kernel/sched.c#L740http://bernia.disca.upv.es/lxr/http/source/kernel/sched.c#L750http://bernia.disca.upv.es/lxr/http/source/kernel/sched.c#L750http://bernia.disca.upv.es/lxr/http/source/kernel/sched.c#L750http://bernia.disca.upv.es/lxr/http/source/kernel/sched.c#L707http://bernia.disca.upv.es/lxr/http/source/kernel/sched.c#L707http://bernia.disca.upv.es/lxr/http/source/kernel/sched.c#L707http://bernia.disca.upv.es/lxr/http/source/kernel/sched.c#L707http://bernia.disca.upv.es/lxr/http/source/kernel/sched.c#L343http://bernia.disca.upv.es/lxr/http/source/kernel/sched.c#L343http://bernia.disca.upv.es/lxr/http/source/kernel/sched.c#L212http://bernia.disca.upv.es/lxr/http/source/kernel/sched.c#L200http://bernia.disca.upv.es/lxr/http/source/include/linux/sched.h#L281http://bernia.disca.upv.es/lxr/http/source/include/linux/sched.h#L281http://bernia.disca.upv.es/lxr/http/source/include/linux/sched.h#L321http://bernia.disca.upv.es/lxr/http/source/kernel/sched.c#L318http://bernia.disca.upv.es/lxr/http/source/kernel/sched.c#L331http://bernia.disca.upv.es/lxr/http/source/kernel/sched.c#L337http://bernia.disca.upv.es/lxr/http/source/include/linux/sched.h#L876http://bernia.disca.upv.es/lxr/http/source/include/linux/sched.h#L884http://bernia.disca.upv.es/lxr/http/source/kernel/sched.c#L318

  • el contador de procesos en dicha cola. del_from_runqueue()[include/linux/sched.h#L876]: Elimina el proceso p de la cola de ejecucin,

    decrementa el contador de procesos en ejecucin y le apunta al proceso el instante en que se ha ido adormir. Se asegura que el puntero next apunte a NULL para el correcto funcionamiento de lafuncin task_on_runqueue().

    move_last_runqueue()[kernel/sched.c#L331] y move_first_runqueue()[kernel/sched.c#L337]:Mueven el proceso p al final de la cola de ejecucin o al principio respectivamente.

    task_on_runqueue()[include/linux/sched.h#L884]: Averigua si el proceso p est en la cola deejecucin.

    Estudio de un S.O. Sincronizacin. Colas de espera.

    7.7 Cola de procesos en ejecucin 5

    http://bernia.disca.upv.es/lxr/http/source/include/linux/sched.h#L876http://bernia.disca.upv.es/lxr/http/source/kernel/sched.c#L331http://bernia.disca.upv.es/lxr/http/source/kernel/sched.c#L337http://bernia.disca.upv.es/lxr/http/source/include/linux/sched.h#L884

    Table of ContentsTema 7. Sincronizacin7.1 Introduccin7.2 Colas de espera: estructuras de datos7.3 Insercin en las colas de espera7.4 Consultando y eliminando elementos de la cola de espera7.5 Durmiendo un proceso7.6 Despertando un proceso7.7 Cola de procesos en ejecucin