Вы находитесь на странице: 1из 17

13- 08-2018

“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

Definición de hebras ............................................................................................................. 4

Estados de un Thread ........................................................................................................... 6

Ventajas ................................................................................................................................. 7

Tipos de hebras ..................................................................................................................... 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

Ejemplos en código ............................................................................................................. 13

Ejemplo en C, utilizando POSIX: ..................................................................................... 14

Conclusión ........................................................................................................................... 16

Bibliografía .......................................................................................................................... 17
Introducción

En sistemas operativos, un hilo de ejecución, proceso ligero, hebra o subproceso es la unidad


de procesamiento más pequeña que puede ser planificada por un sistema operativo, sin
embargo, 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 hebras de un mismo proceso.

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 y Contabilidad.
Como programadores es importante conocer el contenido que tienen las hebras ya que estas
serán visibles para el usuario, pero serán invisibles para el kernel la cual con esto podremos
identificar como funcionan, sus ventajas y desventajas, y principalmente la planificación y
conocer acerca de todo lo relacionado con las hebras, ya sea sus tipos, modelos y estados.
Definición de hebras

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

Los tipos de hebras son: Kernel, usuario y enfoques híbridos [3].

➢ 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:

➢ Cuando un proceso realiza una llamada al sistema bloqueadora no sólo se bloquea la


hebra que realizó la llamada, sino todas las hebras de la tarea.
➢ En un entorno multiprocesador, una aplicación multihebra no puede aprovechar las
ventajas de dicho entorno ya que el núcleo asigna un procesador a un proceso.
[Figura 3: Tipos de hebras]

Modelos de las hebras

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].

[Figura 5: Modelo uno a uno.]

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].

[Figura 6: Modelo muchos a muchos.]


Planificación

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].

Normalmente, la planificación PCS se lleva a cabo de acuerdo con la prioridad: el


planificador selecciona para su ejecución la hebra ejecutable con la prioridad mas alta. Las
prioridades de las hebras de nivel de usuario son establecidas por el programador y no se
ajustan mediante la biblioteca de hebras, aunque algunas bibliotecas de hebras permiten que
el programador cambie la prioridad de una hebra. Es importante destacar que PCS,
normalmente desalojara la hebra actualmente en ejecución en favor de una hebra de prioridad
mas alta; sin embargo, no se garantiza un reparto equitativo de cuantos de tiempo entre las
hebras de igual prioridad [4].
➢ Planificación apropiativa: un hilo puede suspenderse en cualquier punto para dejar
paso a otro hilo, incluso aunque el hilo pueda seguir en ejecución.
➢ Planificación no apropiativa: un hilo se ejecuta hasta que él mismo realiza una
invocación al sistema de gestión de hilos, siendo en ese momento cuando el sistema
puede desalojarle para planificar otro hilo.

La ventaja de la planificación no apropiativa es que cualquier sección de código que no


contenga una llamada al sistema de gestión de hilos es automáticamente una sección crítica.
Así se pueden evitar cómodamente las condiciones de competencia. Por otro lado, los hilos
planificados de forma no apropiativa no pueden aprovechar los sistemas multiprocesador, ya
que se ejecutan de forma exclusiva. Es preciso tener cuidado con las secciones de código
grandes que no contengan llamadas al sistema de gestión de hilos. El programador puede
necesitar insertar invocaciones que permitan que otros hilos puedan planificarse y progresar
en su trabajo. Los hilos planificados de forma no apropiativa no son aptos para su uso en
aplicaciones en tiempo real, ya que en éstas los eventos llevan asociados tiempos absolutos
en los que deben procesarse.

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]:

PTHREAD_SCOPE_PROCESS: planifica las hebras usando la planificación en PCS.

PTHREAD_SCOPE_SYSTEM: planifica las hebras usando la planificación SCS, como


dijimos anteriormente Linux y Mac OSX solo permiten este valor.

En los sistemas que implementan el modelo muchos-a-muchos, la política


PTHREAD_SCOPE_PROCESS planifica las hebras de nivel usuario sobre los procesos
ligeros disponibles. La política de planificación PTHREAD_SCOPE_SYSTEM creará y
asociará un proceso LWP a cada hebra de nivel de usuario en los sistemas muchos-a-muchos.
En otras palabras, asigna un thread de usuario a un thread de kernel, es decir, 1:1.

Las siguientes funciones se utilizan para definir y consultar, respectivamente, el ámbito de


contienda seleccionado:

✓ pthread_attr_setscope(pthread_attr_t *attr, int scope)


✓ pthread_attr_getscope(pthread_attr_t *attr, int *scope)

parámetros → pthread_attr_setscope:

1. Primer parámetro: puntero al conjunto de atributos de la hebra.


2. Segundo parámetro: Se pasa el valor PTHREAD_SCOPE_SYSTEM o
PTHREA_SCOPE_PROCESS según el ámbito de contienda que se desee.
3. Retorno != de cero si se produce error.

parámetros → pthread_attr_getscope

1. Primer parámetro: puntero al conjunto de atributos de la hebra.


2. Segundo parámetro: contiene un puntero a un valor entero (int) al que se le pasa el
valor actual de ámbito de contienda.
3. retorno != de cero si se produce error

Ejemplo en C, utilizando POSIX:

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.

Finalmente, la mayoría de los sistemas operativos modernos proporcionan soporte para


hebras en el kernel; entre ellos se encuentran Windows, NT, 2000 y XP, así como Solaris y
Linux.
Bibliografía

[1] HEBRAS, H. (2018). HILOS Y HEBRAS. Obtenido de


http://sistemasoperativoscaul.blogspot.com/p/hilos-y-hebras.html

[2] (2018). Obtenido de: https://sistop.org/pdf/sistemas_operativos.pdf

[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

[4] Itineracion de hebras - Departamento de Informática. (2018) Obtenido de


http://wiki.inf.utfsm.cl/index.php?title=Itineracion_de_hebras#Ejemplos_en_c.C3.B3digo

Вам также может понравиться