Академический Документы
Профессиональный Документы
Культура Документы
“Planificación
de hebras”
Integrantes:
• Javiera Pino Miranda
• Rodrigo Bravo Piña
• Camila Flores Morales
Curso:
➢ Sistema Operativo
Profesor:
➢ Angel Ubilla V.
Índice
Introducción .......................................................................................................................... 3
Ventajas ................................................................................................................................. 7
Ventajas del uso de las hebras tipo usuario frente a las de tipo kernel: .............................. 8
Desventajas del uso de las hebras tipo usuario frente a las de tipo kernel: ......................... 8
Planificación ........................................................................................................................ 12
Conclusión ........................................................................................................................... 16
Bibliografía .......................................................................................................................... 17
Introducción
Una hebra, hilo, subproceso o también conocido como proceso ligero es un programa en
ejecución que comparte la imagen de memoria y otras informaciones con otros procesos
ligeros. Un proceso puede contener un solo flujo de ejecución, como ocurre en los procesos
clásicos, o más de un flujo de ejecución (procesos ligeros) [1].
Desde el punto de vista de la programación, un proceso ligero se define como una función
cuya ejecución se puede lanzar en paralelo con otras. El hilo de ejecución primario, o proceso
ligero primario, corresponde a la función main.
Cada proceso ligero tiene informaciones que le son propias y que no comparte con otros
procesos ligeros. Las informaciones propias se refieren fundamentalmente al contexto de
ejecución, pudiéndose destacar las siguientes:
➢ Contador de programa.
➢ Pila.
➢ Registros.
➢ Estado del proceso ligero (ejecutando, listo o bloqueado).
Todos los procesos ligeros de un mismo proceso comparten la información de este. En
concreto, comparten:
➢ Espacio de memoria.
➢ Variables globales.
➢ Archivos abiertos.
➢ Procesos hijos.
➢ Temporizadores.
➢ Señales y semáforos.
➢ Contabilidad.
[Figura1: Tareas con una y varias hebras]
Es importante destacar que todos los procesos ligeros de un mismo proceso comparten el
mismo espacio de direcciones de memoria, que incluye el código, los datos y las pilas de los
diferentes procesos ligeros. Esto hace que no exista protección de memoria entre los procesos
ligeros de un mismo proceso, algo que si ocurre con los procesos convencionales.
Una hebra posee: un estado de ejecución (ejecución, listo, etc.), un contexto del procesador
se salva cuando no está ejecutando, una pila de ejecución, almacenamiento estático para las
variables locales y acceso a la memoria y a los recursos del proceso.
Estados de un Thread
Los principales estados de los hilos son: Ejecución, Listo y Bloqueado. No tiene sentido
asociar estados de suspensión de hilos ya que es un concepto de proceso. En todo caso, si un
proceso está expulsado de la memoria principal (RAM), todos sus hilos deberán estarlo ya
que todos comparten el espacio de direcciones del proceso [1].
➢ Creación: Cuando se crea un proceso se crea un hilo para ese proceso. Luego, este
hilo puede crear otros hilos dentro del mismo proceso, proporcionando un puntero de
instrucción y los argumentos del nuevo hilo. El hilo tendrá su propio contexto y su
propio espacio de la columna, y pasará al final de los Listos.
➢ Bloqueo: Cuando un hilo necesita esperar por un suceso, se bloquea (salvando sus
registros de usuario, contador de programa y punteros de pila). Ahora el procesador
podrá pasar a ejecutar otro hilo que esté en la final de los Listos mientras el anterior
permanece bloqueado.
➢ Desbloqueo: Cuando el suceso por el que el hilo se bloqueó se produce, el mismo
pasa a la final de los Listos.
➢ Terminación: Cuando un hilo finaliza se liberan tanto su contexto como sus
columnas.
[Figura 2: Estados.]
Ventajas
➢ Mayor capacidad de respuesta: si una hebra se bloquea, las demás pueden seguir
ejecutándose.
➢ Puede haber varias hebras compartiendo los mismos recursos (memoria, ficheros,
etc.).
➢ Menos costoso que crear procesos, el cambio de contexto también es mas ligero.
➢ Pueden aprovechar arquitecturas multiprocesador.
Tipos de hebras
➢ Hebras usuario:
o Todo el trabajo de gestión de hebras lo realiza la aplicación, el núcleo no es
consciente de la existencia de hebras.
o Se implementan a través de una biblioteca en el nivel usuario. La biblioteca
contiene código para gestionar las hebras: crear hebras, intercambiar datos
entre hebras, planificar la ejecución de las hebras y salvar y restaurar el
contexto de las hebras.
o La unidad de planificación para el núcleo.
➢ Hebras kernel (núcleo):
o Toda la gestión de hebras lo realiza el núcleo.
o El SO proporciona un conjunto de llamadas al sistema similares a las
existentes para los procesos.
o El núcleo mantiene la información de contexto del proceso como un todo y de
cada hebra.
o Las propias funciones del núcleo pueden ser multihebras.
➢ Enfoques híbridos:
o Implementan tanto hebras a nivel kernel como usuario.
o La creación de hebras, y la mayor parte de la planificación y sincronización
se realizan en el espacio de usuario.
o Las distintas hebras de una aplicación se asocian con varias hebras del núcleo
(mismo o menor número), el programador puede ajustar la asociación para
obtener un mejor resultado.
o Las múltiples hebras de una aplicación se pueden paralelizar y las llamadas al
sistema bloqueadoras no necesitan bloquear todo el proceso.
Ventajas del uso de las hebras tipo usuario frente a las de tipo kernel:
➢ Se evita la sobrecarga de cambios de modo, que sucede cada vez que se pasa el control
de una hebra a otra en sistemas que utilizan hebras de tipo kernel.
➢ Se puede tener una planificación para la hebra distinta a la planificación subyacente
del SO.
➢ Se puede ejecutar en cualquier SO. Su utilización no supone cambio en el núcleo.
Desventajas del uso de las hebras tipo usuario frente a las de tipo kernel:
Dado existir una relación entre las hebras de usuario y las del kernel, existen tres formas de
establecer esta relación:
➢ Modelo mucho a uno → asigna múltiples hebras de nivel de usuario a una hebra del
kernel. La gestión de hebras se hace mediante la biblioteca de hebras en el espacio de
usuario, por lo que resulta eficiente, pero el proceso completo se bloquea si una hebra
realiza una llamada bloqueante al sistema. También, dado que sólo una hebra puede
acceder al kernel cada vez, no podrán ejecutarse varias hebras en paralelo sobre
múltiples procesadores [2].
[Figura 4: Modelo muchos a uno]
➢ Modelo uno a uno →Asigna cada hebra de usuario a una hebra de kernel.
Proporciona una mayor concurrencia que el modelo muchos a uno, permitiendo que
se ejecute otra hebra mientras una hebra hace llamada bloqueante al sistema; también
permite que se ejecuten múltiples hebras en paralelo sobre varios procesadores. El
único inconveniente es que crear una hebra de usuario requiere crear la
correspondiente hebra del kernel, dado que la carga de trabajo administrativa para la
creación de hebras del kernel puede repercutir en el rendimiento de una aplicación, la
mayoría de las implementaciones de este modelo restringen el número de hebras
soportadas por el sistema [2].
Modelo muchos a muchos → Multiplexa muchas hebras de usuario sobre un número menor
o igual de hebras del kernel. El numero de hebras del kernel puede ser especifico de una
determinada aplicación o de una determinada máquina (pueden asignarse más hebras del
kernel a una aplicación de un sistema multiprocesador que en uno de un solo procesador).
Mientras que el modelo muchos a uno permiten al desarrollador crear tantas hebras de usuario
como desee, no se consigue una concurrencia real, ya que el kernel solo puede planificar la
ejecución de una hebra cada vez. El modelo uno a uno permite una mayor concurrencia, pero
el desarrollador debe tener cuidado de no crear demasiadas hebras dentro una aplicación. El
modelo muchos a muchos no sufren ninguno de estos inconvenientes. Los desarrolladores
pueden crear tantas hebras de usuario como sean necesarias y las correspondientes hebras del
kernel pueden ejecutarse en paralelo en un multiprocesador. Asimismo, cuando una hebra
realiza una llamada bloqueante al sistema, el kernel puede planificar otra hebra para su
ejecución [2].
En los sistemas operativos que permiten su uso, planifica hebras del nivel del kernel, no
procesos. Las hebras del nivel de usuario son gestionadas por una biblioteca de hebras, y el
kernel no es consciente de ellas. Por ejecutarse en una CPU, las hebras de usuario deben ser
asignadas a una hebra de nivel de kernel asociada, aunque esta asignación puede ser indirecta
y puede emplear un proceso ligero.
Una de las diferencias entre las hebras de nivel de usuario y de nivel del kernel radica en la
forma en que se planifican unas y otras. En los sistemas que implementan los modelos
muchos a uno y muchos a muchos, la biblioteca de hebras planifica las hebras de nivel de
usuario para que se ejecuten sobre un proceso LWP(es como una CPU virtual para un thread
y además, planifican los threads sin necesidad de entrar al kernel) disponible, la cual es un
esquema conocido con el nombre de ámbito de contienda del proceso (PCS, process-
contention scope), dado que la competición por la CPU tiene lugar entre hebras que
pertenecen al mismo proceso. Cuando decimos que la biblioteca de hebras planifica las
hebras de usuario sobre los procesos ligeros disponibles, no queremos decir que la hebra se
ejecute realmente en una CPU; esto requeriría que el sistema operativo planificara la hebra
del kernel en una CPU física. Para decidir qué hebra del kernel planificar en una Cpu, el
kernel usa el ámbito de contienda del sistema (SCS); la competición por la CPU con la
planificación SCS tiene lugar en todas las hebras del sistema. Los sistemas que usan el
modelo uno a uno, planifican las hebras solo con SCS [2].
Ejemplos en código
o Una breve descripción de la API de POSIX:
LA API pthread de POSIX, permite definir el ámbito en el cual se itinerarán los threads al
momento que son creados. Se provee de los siguientes valores para definir el ámbito de
contiendo (sea process-contention scope o system-contention scope) [2]:
parámetros → pthread_attr_setscope:
parámetros → pthread_attr_getscope
4. #include <pthread.h>
5. #include <stdio.h>
6.
7. int main(int argc, char *argv[])
8. {
9. int i, scope;
10. pthread_t tid[NUM_THREADS];
11. pthread_attr_t attr;
12.
13. //Obtener los atributos predeterminados
14. pthread_attr_init(&attr);
15.
16. //Primero consultar el ámbito actual
17. if(pthread_attr_getscope(&attr, &scope) !=0)
18. fprintf(stderr, "Imposible obtener ambito de planificacion\n");
19. else
20. {
21. if (scioe == PTHREAD_SCOPE_PROCESS)
22. printf("PTHREAD_SCOPE_PROCESS");
23. else if (scope == PTHREAD_SCOPE_SYSTEM)
24. printf("PTHREAD_SCOPE_SYSTEM");
25. else
26. fprintf(stderr, "Valor de ambito ilegal .\n");
27. }
28.
29. //Definir el algoritmo de planificación de como PCS o SCS
30. pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
31.
32. //Crear las hebras
33. for (i = 0; i < NUM_THREADS; i++ )
34. pthread_create(&tid[i], &attr, runner, NULL);
35.
36. //Ahora esperar a que termine cada hebra
37. for (i = 0; i<NUM_THREADS; i++)
38. pthread_join(tid[i], NULL);
39.
40. //Cada hebra iniciara su ejecución en esta función
41. void *runner(void *param)
42. {
43. //realizar alguna tarea
44. pthread.exit(0);
45. }
Conclusión
Las hebras son de gran importancia ya que son flujo de control dentro de un proceso. Dentro
de las hebras de usuario se pudo destacar que son visibles para el programador y son
extremadamente desconocidas para el kernel la cual éste soporta y gestiona las hebras del
nivel de usuario, teniendo en cuenta que estas se crean mucho más rápido que las del kernel
ya que no es necesario su intervención. Además, se pudo investigar que existen 3 modelos
diferentes que permiten relacionar estos dos tipos de hebras: el modelo muchos a uno la cual
asigna muchas hebras de usuario a una sola hebra del kernel; el modelo uno a uno que asigna
a cada hebra de usuario la correspondiente hebra del kernel; el modelo muchos a muchos que
multiplexa muchas hebras de usuario sobre un número menor o igual de hebras de kernel.
[3] Viveros, A., Viveros, A., & perfil, V. (2018). 2.3 Procesos ligeros: hilos o hebras.
Obtenido de: http://sitemasoperativosicurosemestre6.blogspot.com/2013/07/23-procesos-
ligeros-hilos-o-hebras.html