Hilos Martes y Mi茅rcoles 19-21 hrs. Sal贸n CEDI 1 Edificio D
M.C. Juan Carlos Olivares Rojas jolivares@uvaq.edu.mx juancarlosolivares@hotmail.com @jcolivares http://antares.itmorelia.edu.mx/~jcolivar
Agenda Introducci贸n Modelos multi-hilo Bibliotecas de hilo Consideraciones sobre los hilos Ejemplos de sistemas operativos
Pendientes
• Práctica de Procesos en Sistemas *X. Miércoles 17 de Febrero. • Cancelada. Investigación sobre IPC en Sistemas Operativos Distribuidos. Martes 23 de Febrero. • Práctica de RPC. Miércoles 24 de Febrero
RPC
• Servidor que va a administrador de procesos.
funcionar
como
• Los clientes se conectan al servidor para ser atendidos y darles un Ticket aleatorio, la atención de estos clientes se hace en forma de round-robin.
Calendarización • Suprimida. Programación de hilos en sistemas *X. Martes 2 de marzo • Programación de Pthreads. Martes 9 de marzo • Programación de hilos en Java. Martes 16 de marzo.
Introducción
• El concepto de hilo es muy similar al concepto de subproceso. • Los hilos van a permitir bifurcar el código de los programas haciendo que las actividades puedan tomar diversos caminos de acción. • Para que puedan realizarse estas actividades de forma concurrente el sistema operativo debe soportarlas.
Concurrencia
• El término concurrencia indica que se tienen dos o más procesos al mismo tiempo en el mismo lugar; esto no implica que se estén ejecutando al mismo tiempo (paralelismo). • El término concurrencia se ha utilizado para indicar que se ejecutan dos o más actividades quasi-paralelamente. En sistemas monoprocesadores esto se logra a través de esquemas de multitarea real y cooperativa.
“Granularidad” del paralelismo
• Cuando queremos explotar el paralelismo, podemos hacerlo en niveles de detalle distintos: – Instrucciones de máquina – Sentencias de un lenguaje de programación – Módulos dentro de un programa – Programas ejecutables completos
• Grano fino grano grueso
“Granularidad” del paralelismo
• El programador debe saber con qué “grano” debe trabajar ante cada problema y no trabajar en niveles de detalle inferior. • Ej. si trabajamos con Ada o Java, estamos en el nivel de “módulos”:
– Concurrencia basada en hilos (threads) – no deberíamos perder el tiempo buscando sentencias simples que se pueden ejecutar en paralelo crear un hilo nuevo para ejecutar una única instrucción no hace ganar tiempo, incluso puede tardar más.
¿Dónde se encuentra la concurrencia?
• En el hardware (la herramienta para construir sistemas informáticos): – ejecución paralela de instrucciones – funcionamiento paralelo de los periféricos – procesadores múltiples – sistemas distribuidos
• En la Naturaleza (los sistemas que modelamos cuando hacemos ingeniería de software) – ¿ejemplos?
Concurrencia inherente o potencial
• Concurrencia inherente:
– Hay sistemas que en los que forzosamente se dan actividades simultáneas. – p.ej. GUI; red de cajeros automáticos; etc.
• Concurrencia potencial:
– Hay sistemas o problemas que se pueden resolver de forma secuencial, pero en los que se puede aprovechar la concurrencia p.ej. para aumentar el rendimiento. – P.ej. multiplicar dos matrices, ordenar un vector…
Concurrencia Unix
â&#x20AC;˘ Los subprocesos se crean con fork() #include <sys/types.h> pid_t pid; pid = fork()
â&#x20AC;˘ Se pueden copiar procesos con la familia de funciones exec.
fork()
if (pid == -1) perror(â&#x20AC;&#x153;Error al crear procesoâ&#x20AC;?); else { if (pid == 0) /*Proceso hijo*/ else /*Proceso padre*/ }
Procesos Padre e Hijos
Señales…
• A el código de estado de un proceso formalmente se llama señal. • Un proceso huérfano es aquel que se ha quedado sin padre. • Un proceso zombi es aquel que se ha quedado ocupando una posición de la tabla de descriptor de procesos.
wait()
• En algunas ocasiones un proceso padre necesita esperar a que sus hijos termine. Para ello necesita sincronizarse los procesos. • La función que nos permite parar un proceso hasta que termine otro es wait • pid = wait(&estado);
wait()
• Algunas macros que nos ayudan en este proceso son: • • • • •
WIFEXITED WEXITSTATUS WIFSIGNALED WTERMSIG WCOREDUMP
Señales • Definidas en <signal.h> • • • • • • • • •
1 SIGHUP 2 SIGINT 3 SIGQUIT 4 SIGILL 5 SIGTRAP 6 SIGIOT 7 SIGEMT 8 SIGFPE 9 SIGKILL
• • • • • • • • • •
10 SIGBUS 11 SIGSEGV 12 SIGSYS 13 SIGPIPE 14 SIGALARM 15 SIGTERM 16 SIGUSR1 17 SIGUSR2 18 SIGCLD 19 SIGPWR
Señales
• int kill(pid, sig) sirve para mandar una señal de un proceso a otro. • pid > 0 proceso; pid = 0 a todos los procesos que pertenecen al mismo grupo. • La función signal sirve para capturar una señal y realizar una función con ella.
Señales
main() { void sigint_handler(); if(signal(SIGINT,sigint_handler)== SIG_ERR) perror(“Error en la señal”); …….. } void sigint_handler(int sig) { printf(“señal recibida”); }
Hilos
• Son procesos ligeros ya que no se duplican completamente, sólo duplican su segmento de código. Por tal motivo, comparten datos fácilmente, la desventaja es que ocurren muchos problemas del tipo “race conditions”, pero al igual que IPC se soluciona con mecanismos como regiones críticas, zonas de exclusión mutua, etc.
Hilos
• Los hilos son procesos ligeros a diferencia de los procesos hijos, los hilos sólo replican el segmento de código, por lo que comparten datos entre otros hilos haciendo mejor uso de la memoria. • La problemática con los hilos es que cada sistema operativo implementa sus hilos de manera distinta. Por ejemplo existen los hilos POSIX, los hilos C de Mach, los hilos en Windows, etc.
Implementaci贸n de Hilos
Procesos en un Servidor Web
Bibliotecas de hilo
• Para la programación de hilos existen diversas APIs. • En el caso de los sistemas *X hasta no hace mucho (y de hecho aun muchos sistemas se siguen implementando con procesos hijos) se empezó a realmente a estandarizar el uso de hilos. • Lenguajes concurrentes como ADA, modula2, Java y actualmente casi todos los Sistemas Operativos lo implementan.
Hilos
• PThreads (POSIX Threads) es la biblioteca para la creación de hilos más implementada en sistemas *X. • Se utiliza la biblioteca pthread por lo que algunos compiladores ya la incluyen de manera predeterminada sino habrá que indicar su uso: gcc … -lpthread
Hilos
• Crear hilos: int pthread_create(pthread_t *thread, pthread_attr_t *attr, void * (*start_routine)(void *), void *arg) • Esperar la finalización de hilos: int pthread_join(pthread_t **thread_return)
th,
void
Hilos
• No guardar estado del hilo: int pthread_detach(pthread_t h) • Salir de un hilo: pthread_exit(void *retval) • Biblioteca a utilizar: #include <pthread.h>
Hilos
typedef struct parametros { };
int id; char *nombre
void *funcion(parametros *p) { }
printf(â&#x20AC;&#x153;%s %dâ&#x20AC;?, p->cadena, p->id); pthread_exit(&(p->id))
Hilos
• Referencia asi mismo: Yo = pthread_self(); /*Demás funciones*/ • Enviar una señal a un hilo: pthread_kill(pthread_t hilo, int señal); • Los hilos no están tan extendidos por que existen muchas variantes: hilos mach, hilos solaris, Gthreads, etc.
â&#x20AC;˘ Mutex:
Hilos
pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutex_attr_t *attr) int pthread_mutex_lock(pthread_mutex_t *mutex) int pthread_mutex_lock(pthread_mutext_t *mutex) int pthread_mutext_destroy(pthread_mutext_t *mutex)
Hilos
• En general los hilos en Java debido a su portabilidad binaria son idénticos en todas las plataformas. Existen dos formas básicas de implementar procesos: heredar de la clase Thread o bien implementar la interfaz Runnable. • En general en el método public void run() se agrega la funcionalidad del hilo.
Hilos
• Si se heredo de la clase Thread el hilo debe crearse de la siguiente forma: • Thread hilo = new Thread(new Objeto()); • El método Thread.sleep(ms); permite dormir un proceso n cantidad de milisegundos.
Hilos
• En general se ejecuta el hilo poniendo el método start(), e.g.: hilo.start(); • Otros métodos de los hilos son: isAlive() para determinar si un hilo está con vida, el metodo stop()* finaliza un hilo, el método suspend()* lo suspende, el método resume() reanuda un proceso y join() espera a que finalice un proceso especificado.
Hilos
• Se pueden asignar prioridades a los hilos con el método setPriority(), en donde la prioridad puede ser MIN, MAX y NORM_PRIORITY. • El método yield() cede prioridad, mientras que el método setDaemon(true) hace que un hilo sea demonio.
Hilos
• Los demonios son hilos que pueden correrse sin depender de otros procesos. Se utilizan mucho para la programación de servicios del sistema. • Se pueden crear grupos de hilos con la clase GroupThread para un mejor manejo.
Consideraciones sobre los hilos
• El manejo de hilos no necesariamente eficientiza el uso de los recursos. • Para aprovechar los hilos debe de ser necesario diseñar aplicaciones que hagan uso exclusivo de hilos, de muy poco se agiliza una aplicación como Word si es que cuenta con 4 núcleos de procesamiento. • Los SO deberían de paralelizar aplicaciones pero es sumamente difícil hacerla.
Ejemplos de sistemas operativos
• Actualmente prácticamente todos los sistemas operativos tienen soporte para hilos y multitareas, incluyendo los dispositivos móviles (sólo una tarea es principal, las demás son secundarias). • El uso de sistemas operativos monotarea es realmente difícil de encontrar en aplicaciones actuales, sólo en aquellos dispositivos empotrados (de bajo costo) de uso muy específico se sigue viendo.
Paralelismo
• El problema del paralelismo radica en que muchos algoritmos no pueden paralelizarse (son serializable o secuenciales). • Existen dos paralelismo:
tecnologías
para
realizar
– PVM (Parallel Virtual Machine) [7] – MPI (Message Parking Interface) [8][9][10]
Algoritmo paralelos
for(int i = 0; i < 4; i++) { }
aleatorio(i);
aleatorio(1) micro1 aleatorio(2) micro2 aleatorio(3) micro3 aleatorio(4) en espera • Compilador optimizados
optimizado.
Sistemas
Operativos
Algoritmos paralelos a11 a 21 am1
a12 a22 am 2
a1n x1 b1 a2 n x2 b2 = amn xn bm
Conviene
No conviene
Algoritmos paralelos
• Instrucciones como while son más difíciles de paralelizar por que depende de la condición. • No siempre los compiladores pueden paralelizar de manera automática un algoritmo. • En algunas ocasiones se invierte más tiempo tratando de paralelizar un algoritmo que ejecutándolo de manera secuencial.
Algoritmos paralelos //Procesador uno for( i=0; i<N/2; i++) { a[i]= c+i; }
//Procesador uno for( i=0; i<N/2; i++) { a[i]= c+i; }
//Procesador dos for( ; i<N; i++) { a[i]= c+i; }
//Procesador dos for( i = N/2; i<N; i+ +) { a[i]= c+i; }
Algoritmos paralelos A[0] = C; //Procesador uno for( i=1; i<N/2; i++) { a[i]= a[i-1]+1; } //Procesador 2 for( i=N/2; i<N; i++) { a[i]= a[i-1]+1; }
• ¿Por qué no se puede paralelizar? • Por que el segundo proceso depende del resultado del primero. • Si se puede si se encuentra un algoritmo que permita encontrar el valor de a[N/2] directo.
N /2
∑i i =C
Caso práctico MPI
• Existen diversas implementaciones de MPI: LAM/MPI, MPICH, MPICH2, OpenMPI • MPI se puede programar en C o Fortran. • El primer paso es tener nuestro programa paralelo y asegurarnos de que está corriendo el demonio de MPI: • mpd –ncpus=procesadores & •
Caso Práctico MPI
• Se debe compilar el programa: • mpicc holamundo.c –o holamundo
• Se debe de correr el proceso idicando el número de procesadores: • mpirun –np 10 ./holamnudo
Holamundo.c en MPI
#include <stdio.h> #include “mpi.h” int main(int argc, char **argv) { int procesos, rango, tam; char nombre[MPI_MAX_PROCESSOR_NAME]; MPI_Iinit (&argc, &argv); MPI_Comm_size(MPI_COMM_WORLD, &procesos); MPI_Comm_rank(MPI_COMM_WORLD, &rango); MPI_Get_processor_name(nombre, &tam); MPI_barrier(MPI_COMM_WORLD); printf(“Hola, mundo!, soy %d de %d y me ejecuto en:%s\n”, rango, procesos, nombre); MPI_Finalize(); return 0; }
Esquema de un programa en MPI
Esquema de un programa en MPI /*Cabecera de MPI*/ #include <mpi.h> int main(int argc, char **argv) { int quiensoy, tamano; MPI_Status estado; /*Inicializamos MPI*/ MPI_Init(&argc, &argv); /*Preguntamos quienes somos*/ MPI_Comm_rank(MPI_COMM_WORLD, &quiensoy);
/*Nos esperamos hasta quetodos hayan inicializado MPI*/ MPI_Barrier(MPI_COMM_WORLD); /*Preguntamos cuanto somos*/ MPI_Comm_size(MPI_COMM_WORLD, &tamano); /*PROGRAMA*/
Esquema de un programa en MPI
}
if(quiensoy == root) { /*Inicializaci贸n estrructuras repartidor Reparte tareas Espera resultados Visualiza resultados*/ } else { /*recibe la tarea realiza c谩lculos manda resultados*/ } /*Finaliza el programa*/ MPI_Finalize(); exit(0);
Paralelización Multiplicación de Matrices • Programa secuencial de multiplicación de matrices en Java o C. • Programa concurrente, partir del hecho de que se puede poner un hilo en ejecución para multiplicaciones no dependientes.
Sistemas de tiempo real
• Son sistemas para poder ejecutar satisfactoriamente tareas que han de completarse en un plazo prefijado de tiempo (ej. sistemas de control industrial, sistemas multimedia, sistemas de misión crítica). • Se caracterizan porque los procesos tienen que ejecutar en instantes predeterminados.
Clasificación de STR
• Existen dos tipos de STR:
• Crítico (rígido): para tareas que siempre deben cumplir los plazos de terminación. Adecuados para la industria. Muy simples, incompatibles con tiempo compartido, memoria virtual, etc. • No crítico (flexible): intentan cumplir los plazos, pero no los garantizan al 100%. Adecuados para multimedia, etc.
• Aeronave
• Carro
Ejemplo de STR
Sistemas Embebidos de TR
Aplicaciones de los STR
• Dominio Industrial
– Controlador de la planta – Robot para tratamiento de material peligroso
• Uso militar
– Sistema de reconocimiento de blancos automático – Sistema de guiado de misiles y navegación
• Sistemas altamente críticos – Plantas nucleares – Sistemas de aviónica
Sistemas de Tiempo Real
• Los tipos de tiempo pueden ser:
– Los de plazo fijo se ejecutan una vez en un instante determinado. – Los periódicos se ejecutan cada cierto tiempo.
• Los sistemas en tiempo real críticos tienen asignada una franja de tiempo que no pueden rebasar.
Sistemas de Tiempo Real
• Suelen tener pocos procesos en estado de listo a fin de que no se retrase la ejecución de los mismos. • Se introducen retardos en la ejecución, como puede ser la memoria virtual, puesto que la paginación puede producir retrasos inadmisibles para el proceso. • Los STR son altamente tolerante a fallas manejados por el sistema.
Arquitecturas de Tiempo Real Sistema en Tiiempo Real Distribuido. Arqutecturas homogeneas o heterogeneas. Redes de area local, y topologias de red. Protocolos de comunicaciones:Ethernet, Token Ring Modelo OSI. Redes FFDI, X-25, ATM.
E/S Digital
E/S Analógico Medio Ambiente
Comunicaciones
Otras Computadoras
Software de Tiempo-Real Microcontroladores y sistemas embebidos. DSP’s, PLC’s. Buses de multiprocesadores: VMEBUs,Multibus,FutureBus Arquitecturas RISC, Transputers. Uniprocesadores, Multiprocesadores. Memorias chache, DMA’s.
Reloj
Computadora (HW)
Otras E/S
Ejemplo de un sistema en tiempo real.
Actividades en una computadora de automobil.
Control de Velocidad
C=4ms. T=20ms. D=5ms.
Control de combustible
Control de Frenado
C=40ms. T=80ms. D=80ms.
C=10ms. T=40ms. D=40ms.
Otro software no-critico
C=10ms. T=40ms.
tiempo de computo (peor caso), T=Periodo de ejecucion, D=Plazo de respuesta
Solucion Ciclica. 76
combustible-2
64 vel. 60
0
4
no velocidad critico
frenado
* implica descomponer actividades grandes en varias ejecuciones.
com busti ble-3 54
14 com busti ble-1 20 vel. 24
frenado
combustible-2
velocidad 44
40
Solucion Concurrente. La solucion concurrente es mas simple de disenar y modificar. task body speed is begin loop speed_measurement; next:=next+0.2 sleep_until_next; end loop end speed
task body fuel is begin loop fuel_injection; next:=next+0.2 sleep_until_next; end loop end speed
task body brake is begin loop control_brakes; next:=next+0.2 sleep_until_next; end loop end speed
task body non_critical is begin loop perform computation; end loop end speed
Sistemas Distribuidos de TR
• Son totalmente más complejos debido a la gran heterogeneidad de sus componentes. • Debido a esta problemática son poco los Sistemas Operativos Distribuidos de Tiempo Real aunque muchos SO de Tiempo Real (ej. SO de dispositivos empotrados) tienen capacidad de comunicación distribuida.
Sistemas Operativos de TR
• El problema de la distribución radica en los tiempos de latencia de los mecanismos de comunicación distribuida (sockets, RPC, middlewares, etc.) dado que no hay una garantía de servicio y más si se enfoca en redes públicas como la Internet. • En la práctica la gran mayoría de los Sistemas Operativos Distribuidos de Tiempo Real se llegan a implementar en sistemas multiprocesadores.
Sistemas Operativos Distribuidos de TR
• La mayoría de los sistemas operativos distribuidos de tiempo real caen en el área de multimedia (QNX) y de los sistemas empotrados (Symbian). Los sistemas de navegación son otro claro ejemplo de SOTR.
SOD de Tiempo Real
• Estos sistemas deben de ser determinísticos y predecibles.
totalmente
• Otro tópico que es un gran reto en este tipo de sistema es la seguridad y en específico el control de acceso. • El balanceo de cargas de trabajo es de suma importancia para el uso eficiente del sistema
SOD de Tiempo Real
• La concurrencia y sincronización de procesos es aún más complicada (un recurso que es utilizado por un proceso debe de ser liberado automáticamente para que otro proceso más crítico pueda trabajar inmediatamente). • La selección de hardware es más compleja. • La caracterización (medición de tiempos) de estos sistemas es compleja y no muy exacta.
SOD de Tiempo Real
• El uso de SOD de Tiempo Real tiene que ser manejado con las aplicaciones, ya que de lo contrario no tendría una utilidad práctica; por este motivo, es necesario la adaptación de herramientas como: compiladores, utilerías, base de datos y software de sistema.
Referencias
• Liberty, Jesse, Horvarth, David (200). Aprendiendo C++ para Linux en 21 Días. México, Prentice Hall. • Márquez, Francisco (1994). Unix Programación Avanzada. Estados Unidos, Addison-Wesley.
Referencias
• Colouris, George, Dollimore, Jean, Kindberg, Tim (2001). Sistemas Distribuidos Conceptos y Diseño. 3a. Edición. España, Pearson AddisonWesley. • Horstmann, Cay, Cornell, Gary (2006). Core Java 2 Volumen II Carácterísticas Avanzadas. España, Perason Prentice Hall.
Referencias
• Deitel, Harvey, Deitel, Paul (2004). Java Como Programar. Quinta Edición. México, Pearson Prentice Hall. • Márquez, Francisco (2004). UNIX Programación Avanzada. Tercera edición, México, Alfaomega Ra-Ma.
Referencias
• Tanenbaum, Andrew (1996). Sistemas Operativos Distribuidos. México, Prentice Hall. • Tanenbaum, Andrew, Van Steen, Maarten (2006). Distributed Systems Principles and Paradigms. Estados Unidos, Pearson Prentice Hall. • Mejía, P. (2009), Curso de Sistemas de Tiempo Real, CINVESTAV, México.
多Preguntas, dudas y comentarios?