Documentos de Académico
Documentos de Profesional
Documentos de Cultura
4 STR
4 STR
TEMA:
“CAPÍTULO 4: CONCEPTOS Y PRÁCTICA DE LABORATORIO”
Subtitle
DOCENTE:
Ing. CIP Daniel Leonardo Barrera Esparta
I.- HILOS Y PROCESOS
Cada programa está compuesto por uno o varios procesos
- Cada proceso dispone de su propio espacio virtual protegido de memoria para datos
globales, datos dinámicos y código, además de recursos solicitados al sistema operativo (ej.
ficheros).
- Cada proceso se ejecuta en uno o varios hilos (threads).
- Cada hilo corresponde a una línea de ejecución secuencial de instrucciones y dispone de
pila propia (datos locales, retornos de rutinas) e información de contexto propia (registros
de la CPU, estado).
I.- HILOS Y PROCESOS
Interacción entre procesos
• Servicios ofrecidos por el sistema operativo como intermediario.
• Datos: colas de mensajes, memoria compartida.
• Sincronización: semáforos, monitores, etc.
• Señales
I.- HILOS Y PROCESOS
Hilos (Threads)
Ejemplos:
- Windows 95/98/NT/2000
- Solaris
- Tru64 UNIX
- BeOS
- Linux
I.- HILOS Y PROCESOS
Aplicación: sistema de control
Arquitectura de software
Hay tres actividades concurrentes:
• Control de presión.
• Control de temperatura.
• Visualización,
Se puede hacer de tres formas:
✓ Con un solo programa secuencial (ejecutivo cíclico ). No hace falta sistema operativo
✓ Con tres procedimientos secuenciales ejecutados como procesos de un sistema operativo
✓ Con un solo programa en un lenguaje concurrente . No hace falta sistema operativo, pero sí
un núcleo de ejecución.
I.- HILOS Y PROCESOS
Problemas:
• La temperatura y la presión se muestrean con la misma frecuencia.
• Mientras se espera leer una variable no se puede hacer nada con la otra. Si un sensor falla,
deja de leerse el otro también.
• Se basa en una espera ocupada. Además ambas actividades deberían estar desacopladas.
• El principal problema es que dos actividades independientes están acopladas entre sí
• Se utiliza un único programa que ignora la concurrencia lógica de T, P y S => No es necesario
sistema operativo.
I.- HILOS Y PROCESOS
Solución con ejecutivo
cíclico
• Es más fácil de
escribir y leer
• El código refleja
directamente el
paralelismo de la
aplicación
• Problema: Ambas
tareas hacen uso de
la pantalla => hace
falta gestionar el
• Acceso a este
recurso compartido.
I.- HILOS Y PROCESOS
Problemas
• int pthread_ create( pthread_ t *thread, pthread_ attr_ t *attr, void *(* start_ routine)( void *),
void *arg);
Crea un thread con sus atributos, rutina inicial y argumentos de esta
int main()
{
pthread_t threads[NUM_THREADS];
int rc, t;
for(t=0;t < NUM_THREADS;t++){
II.- PROGRAMACIÓN EN HILOS
Ejemplo 2
if (pthread_create(&th1, NULL, periodic,
#include <pthread.h> &period1)==-1)
void * periodic (void *arg) { {
int period; perror("");
period = *((int *)arg); }
while (1) { if (pthread_create(&th2, NULL, periodic,
printf("En tarea con periodo %d\n", period); &period2)==-1)
sleep (period); {
} perror("");
} }
main() { sleep(30);
pthread_t th1, th2; printf("Salida del hilo principal\n");
int period1, period2; exit(0);
period1 = 2; }
period2 = 3;
II.- PROGRAMACIÓN EN HILOS
Atributos con los Hilos
• int pthread_ attr_ getdetachstate( const pthread_ attr_ t *attr, void *detachstate);
Devuelve el estado detach de un atributo de thread. Un thread detached no es joinable
• int pthread_ attr_ setdetachstate( pthread_ attr_ t *attr, void *detachstate);
Establece el estado detach de un atributo de thread
• int pthread_ attr_ setscope( pthread_ attr_ t *attr, int contention _scope);
Establece el ámbito de contienda del atributo de un thread
• Int pthread_ attr_ getscope( pthread_ attr_ t *attr, int *contention_ scope);
Devuelve el ámbito de contienda del atributo de un thread
• int pthread_ attr_ setschedpolicy( pthread_ attr_ t *attr, int policy);
Establece la política de planificación del atributo de un thread
• int pthread_ attr_ getschedpolicy( pthread_ attr_ t *attr, int *policy);
Devuelve la política de planificación del atributo de un thread
II.- PROGRAMACIÓN EN HILOS
Ejemplo 3 pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr,
#include <pthread.h> PTHREAD_CREATE_UNDETACHED);
#include <stdio.h> for(t=0;t < NUM_THREADS;t++) {
#define NUM_THREADS 3 printf("Creating thread %d\n", t);
void *BusyWork(void *null){ rc = pthread_create(&thread[t], &attr,
int i; double result=0.0; BusyWork, NULL);
for (i=0; i < 1000000; i++) { }
result = result + (double)random(); } /* libero atributo y espero a los otros hilos */
printf("result = %d\n",result); pthread_attr_destroy(&attr);
pthread_exit((void *) 0); for(t=0;t < NUM_THREADS;t++)
} { pthread_join(thread[t], (void **)&status);
void main(){ pthread_t thread[NUM_THREADS]; printf("Completed join with thread %d status=
pthread_attr_t attr; %d\n",t, status); } pthread_exit(NULL);}
int rc, t, status;
/* Initialize and set thread detached attribute */
II.- PROGRAMACIÓN EN HILOS
Ejemplo 3
II.- PROGRAMACIÓN EN HILOS
MUTEX
Hay dos mecanismos que permiten sincronizar hilos:
• Un mutex es una variable que proporciona exclusión mutua mediante dos operaciones, lock y
unlock
• una variable de condición proporciona sincronización condicional mediante dos operaciones,
wait y signal
Ambos tipos de variables pueden tener atributos
II.- PROGRAMACIÓN EN HILOS
MUTEX
• int pthread_ mutex_ init( pthread_ mutex_ t *mutex, pthread_ mutexattr_ t *attr);
Inicializa un mutex con ciertos atributos.
• int pthread_ mutex_ destroy( pthread_ mutex_ t *mutex);
Destruye el mutex. Comportamiento indefinido si el mutex está cerrado.
• int pthread_mutexattr_init (attr)
Crea un objeto atributo mutex e inicializa con valores por defecto.
• int pthread_mutexattr_destroy (attr)
Elimina el objeto de atributo de mutex attr
• int pthread_ mutex_ lock( pthread_ mutex_ t *mutex);
Cierra el mutex.El propietario del mutex es el thread que lo cerró.
• int pthread_ mutex_ unlock( pthread_ mutex_ t *mutex);
Abre el mutex cuando lo invoca su thread propietario Comportamiento indefinido si no es el
thread propietario o el mutex está abierto. Activa un thread suspendido en el mutex.
II.- PROGRAMACIÓN EN HILOS
Ejemplo
#include <pthread.h>
#include <stdio.h>
struct { int data[1]; /* buffer compartido */
pthread_mutex_t mutex; /* mutex */ }
buffer;
int main(void) {
pthread_t rd; /* id del consumidor */
pthread_attr_t attr; /* atributos */
int valores[50], indice,in, c,x;
void *status; /* exit thread status */
void *consumidor(void *); /* prototipo */
void escritura(int); /* prototpo */
II.- PROGRAMACIÓN EN HILOS
Ejemplo
mutex_init(&buffer.mutex,NULL) /* inicializa el mutex*/
pthread_attr_init(&attr); /* inicializa atributos de hilo*/
pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_JOINABLE );
/* create hilo consumidor */
pthread_create(&rd,&attr,consumidor,NULL)
// lleno valores a escribir y leer
for(indice=0;indice<15;indice++)
{ valores[indice]=indice; }
valores[indice]=50;
//---------------------- PRODUCTOR ------------------------//
/* el main es el hilo productor */
indice=0;
do { c=valores[indice++]; /* lee un valor */
escritura(c); /*produce/almacena en buffer. */ }
while (c !=50); / * continua hasta que dato es 50 */
II.- PROGRAMACIÓN EN HILOS
Ejemplo
void escritura(int c) {
int xx; pthread_mutex_lock(&buffer.mutex); /* lock mutex */
buffer.data[1] = c; /* inserta un dato */
pthread_mutex_unlock(&buffer.mutex); /* unlock mutex */
}
int lectura() {
int elem, c;
pthread_mutex_lock(&buffer.mutex); /* lock mutex */
elem = buffer.data[1]; /* lee un dato */
c=elem; printf("%3d",c); /* imprime valor */
pthread_mutex_unlock(&buffer.mutex); /* unlock mutex */
return elem; }
II.- PROGRAMACIÓN EN HILOS
Variable de condición
◼Variables de Condición(VC) proveen otra manera de sincronizar hilos. Mientras que los
Mutexs implementan sincronización controlando al hilo el acceso de dato, las variables
de condición permiten sincronizar hilos en base al valor actual del dato
◼Sin VC, el programador podría tener hilos que continuamente estén polling
(posiblemente en una sección critica),para verificar si una condición se mantiene.
pthread_cond_init(condition, attr)
Inicializa una vc y fija sus atributos
pthread_cond_destroy(condition)
libera una VC que ya no es necesario
pthread_condattr_init(attr)
pthread_condattr_destroy(attr)
estas rutinas son usado para crear y destruir atributos de la variable de condición.
II.- PROGRAMACIÓN EN HILOS
Variable de condición
pthread_cond_signal(condition)
Se usa para señalar o despertar otro hilo el cual esta esperando sobre la VC. Este debe ser
llamado después que el mutex es is locked, y debe unlock mutex para que
thread_cond_wait()complete
II.- PROGRAMACIÓN EN HILOS
Variable de condición
#include <pthread.h>
#include <stdio.h>
struct { int data[1]; /*buffer comnpartido */
pthread_mutex_t mutex; /* mutex */
pthread_cond_t cond; /* variable de condition */
} buffer;
int nnElem=0; //indica si el buffer esta lleno/vacio int main(void)
{ pthread_t rd; /* id del consumidor */
pthread_attr_t attr; /* atributos */
int valores[50],indice, c,x;
void *status; /* exit thread status */
void *consumidor(void *); /* prototype */
void write_to_buffer(int); /* prototype */
II.- PROGRAMACIÓN EN HILOS
Variable de condición
indice=0;
/* inicializa mutex */
pthread_mutex_init(&buffer.mutex, NULL)
/* initicializa variable de condicion */
pthread_cond_init(&buffer.cond, NULL) /*
inicializa atributos de hilo */ pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_JOINABLE );
/* crea hilo consumidor */
pthread_create(&rd,&attr,consumidor,NULL)
{valores[indice]=indice;} valores[indice]=50;
II.- PROGRAMACIÓN EN HILOS
Variable de condición
//--------------------CONSUMIDOR ------------------------------
void *consumidor(void *arg)
{ int c; int read_from_buffer(); /* prototype */
do { c = read_from_buffer(); /* lee un dato */
} while (c != 50);
}
void write_to_buffer(int c) {
pthread_mutex_lock(&buffer.mutex); /* lock mutex */
if (nnElem == 1) //si esta lleno no escribe /* no puede escribir, buffer full ==> espera */
pthread_cond_wait(&buffer.cond,&buffer.mutex); buffer.data[tamano] = c; /* inserta data */
nnElem=nnElem+1; /* increase para indicar lleno */
/* despierta el hilo consumidor */
pthread_cond_signal(&buffer.cond); pthread_mutex_unlock(&buffer.mutex); /* unlock mutex*/ }
II.- PROGRAMACIÓN EN HILOS
Variable de condición
int read_from_buffer() {
int elem,c;
pthread_mutex_lock(&buffer.mutex); /* lock mutex */
if (nnElem == 0) /* no puede leer, buffer vacio ==> espera */
pthread_cond_wait(&buffer.cond,&buffer.mutex);
elem = buffer.data[tamano]; /* consume un dato */
nnElem=nnElem-1; /* decrementa para indicar vacio*/
/* despierta al hilo productor*/
pthread_cond_signal(&buffer.cond);
pthread_mutex_unlock(&buffer.mutex); /* unlock mutex */
return elem; }
II.- PROGRAMACIÓN EN HILOS
Productor y consumidor
III.- SEÑALES
Señales en POSIX.
• Son interrupciones software (suceso asíncrono) que pueden ser enviadas a uno o mas
procesos/threads para informarle de la ocurrencia de un evento.
• Señal es a proceso como interrupción es a procesador
• Una señal es gestionada por el S.O.
• Una señal interrumpe la tarea actualmente en curso y se activa la tarea asociada a la señal.
• Permite asociar señales independientes a cada proceso o thread
• Una señal se puede producir o generar de varias formas, por ejemplo:
✓fallos de hardware
✓expiración de temporizadores
✓un acción explícita de otro proceso o thread, invocando la función kill() u otra similar
III.- SEÑALES
Identificadores de señal
Cada tipo de señal se identifica mediante un número entero positivo
Se definen constantes (etiquetas) para dar nombres simbólicos a las señales
Ejemplos:
SIGABRT ‘abort signal’
Terminación anormal
Se genera cuando se llama a la función abort()
Causa la terminación del proceso
No debe ser ignorada
SIGALRM ‘alarm signal’
Fin de temporización
Se genera cuando expira el tiempo
programado con alarm() o con setitimer()
SIGFPE ‘floating point exception signal’
operación aritmética errónea
Ejemplo: dividir por cero, desbordamiento (overflow)
III.- SEÑALES
Identificadores de señal
SIGINT ‘interruption signal’
Señal de atención interactiva
Se envía a proceso asociado a un terminal cuando se pulsa la tecla interrupción [CTRL-C]
Acción por defecto terminar el proceso
SIGKILL ‘kill signal’
Señal de terminación abrupta
No puede ser ignorada ni armada
Acción por defecto genera ‘core’ + terminar proceso
III.- SEÑALES
Identificadores de señal
Armado de una señal: Indicarle al sistema operativo el nombre de la rutina que ha de tratar
cuando llegue ese tipo de señal POSIX ---- > sigaction( ) System V ---- > signal( )
Ignorar una señal : Algunas se pueden ignorar y otras se pueden enmascarar momentáneamente
Acción por defecto: Cuando un proceso recibe una señal sin haberla armado o enmascarado
previamente. En la mayoría de los casos consiste en matar al proceso
III.- SEÑALES
III.- SEÑALES
Tratamiento de usuario