Está en la página 1de 17

TEMA 10:

SISTEMAS OPERATIVOS
Y TIEMPO REAL

Bibliografa:

Informtica Industrial. Grado en Electrnica Industrial y Automtica


Departamento de Sistemas Informticos- UCLM

CONTENIDOS

Programando con hilos en Windows

Introduccin al concepto de hilo


Por qu debemos usar hilos?
Creacin de hilos en Windows
Cierre de hilos en Windows
Espera de hilos en Windows
Ejemplo de creacin de hilo completo y correcto
Creacin de mltiples hilos en Windows
Mltiples hilos mediante vector de hilos
Paso de parmetros a un hilo
Paso de parmetros de forma correcta
Seccin Crtica en Windows
Finalizacin de hilos en Windows
Finalizacin de hilos en Windows (instruccin de emergencia)

Informtica Industrial. Grado en Electrnica Industrial y Automtica


Departamento de Sistemas Informticos- UCLM

Programando con hilos en Windows

Introduccin al concepto de hilo

Formalmente, en un sistema operativo, un hilo de ejecucin,


hebra o subproceso es la unidad de procesamiento mnima que
puede ser planificada por un sistema operativo.

La creacin de un hilo es una caracterstica que permite a un


programador realizar varias tareas a la vez (simultneamente),
aprovechando al mximo los recursos de una mquina (Intel
Core i7 , por ejemplo). Los distintos hilos de ejecucin
pueden, y de hecho lo hacen, compartir recursos: el espacio de
memoria para el almacenamiento de variables, los archivos,
etc. Adems, la programacin empleando hilos nos permite
simplificar el diseo de un programa, cuando ste ejecuta ms
de una funcin a la vez. Resumiendo, un hilo es simplemente
un conjunto de instrucciones que pueden ser ejecutadas al
mismo tiempo que el conjunto de instrucciones de otro hilo.

Informtica Industrial. Grado en Electrnica Industrial y Automtica


Departamento de Sistemas Informticos- UCLM

Programando con hilos en Windows

Por qu debemos usar hilos?


Ventajas:
Mayor rendimiento. La creacin de hilos es un mecanismo sencillo de aprovechar los
procesadores con mltiples ncleos.
Mejor uso de los recursos. Incluso en sistemas basados en un solo procesador, la utilizacin
de hilos reduce la latencia. Por ejemplo, el bloqueo de un hilo a la espera de recibir un dato a
travs de un dispositivo de entrada/salida no bloquear al resto de hilos pendientes.
Uso de los datos de forma compartida. La informacin puede ser compartida directamente
por los hilos, empleando la memoria del sistema.

Inconvenientes:
La programacin de aplicaciones se vuelve compleja.
La depuracin del cdigo es compleja, debido a la ejecucin de forma simultnea de varios
hilos a la vez.

Informtica Industrial. Grado en Electrnica Industrial y Automtica


Departamento de Sistemas Informticos- UCLM

Programando con hilos en Windows

Creacin de hilos en Windows

Cada hilo de Windows es declarado mediante un tipo de variable denominado HANDLE,


empleando una funcin denominada CreateThread(). Dicha funcin nos devolver un identificador
de hilo de tipo HANDLE.

Los hilos se controlan a travs de su HANDLE: creacin, espera, finalizacin, etc., es decir, todas
las operaciones que realicemos sobre ellos sern a travs de dicho identificador.

Prototipo de la funcin de creacin de hilo en Windows, incluida en la librera Windows.h, en el


lenguaje de programacin C++:
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES ThreadAttributes,
DWORD StackSize,
LPTHREAD_START_ROUTINE StartAddress,
LPVOID Parameter,
DWORD CreationFlags,
LPDWORD ThreadId );

Informtica Industrial. Grado en Electrnica Industrial y Automtica


Departamento de Sistemas Informticos- UCLM

Programando con hilos en Windows

Cierre de hilos en Windows

De

esta

forma,

el

hilo

ejecutar

la

funcin

especificada

en

el

parmetro

LPTHREAD_START_ROUTINE StartAddress.

Las funciones ejecutadas por los hilos tendrn las siguientes caractersticas:

Devolvern un tipo especial de valor de tipo DWORD WINAPI

Solamente admitirn un parmetro de tipo LPVOID

Su prototipo ser DWORD WINAPI <nombre_de_la_funcin>(LPVOID pArg)

Una vez acabemos la ejecucin del hilo debe de ejecutarse la funcin CloseHandle(), para
indicarle al sistema operativo que el hilo ha finalizado y debe ser cerrado. Ejemplo:
#include <stdio.h>
#include <windows.h>
DWORD WINAPI hijo(LPVOID pArg){
printf("Hola!! Soy el hijo\n");
return 0;
}
int main (void){
HANDLE hilo=CreateThread(NULL,0,hijo,NULL,0,NULL);
CloseHandle(hilo);
return 0;
}

Informtica Industrial. Grado en Electrnica Industrial y Automtica


Departamento de Sistemas Informticos- UCLM

Programando con hilos en Windows

Espera de hilos en Windows

Sin embargo, en el ejemplo anterior, puede darse el caso de que no se imprima nada. Por qu?
Porque cuando un proceso acaba, todos sus hilos terminan. El programa principal tambin es un
hilo, por lo que si finaliza antes de que finalice su hilo hijo, ste tambin lo har.

Para evitar esto, se utilizar la funcin WaitForSingleObject(), cuyo prototipo es el siguiente:


DWORD WaitForSingleObject(
HANDLE hHandle,
DWORD dwMilliseconds);

De esta forma, el hilo creador de hilos (el padre o programa principal), esperar hasta que su hilo
hijo finalice. Se dice, en este caso, que el padre est bloqueado hasta que el hijo finalice.

Especificando INFINITE en el parmetro dwMilliseconds, esperaremos de forma indefinida a que


el hilo hijo finalice.

Informtica Industrial. Grado en Electrnica Industrial y Automtica


Departamento de Sistemas Informticos- UCLM

Programando con hilos en Windows

Ejemplo de creacin de hilo completo y correcto


#include <stdio.h>
#include <windows.h>
DWORD WINAPI hijo(LPVOID pArg){
printf("Hola!! Soy el hijo\n");
return 0;
}
int main (void){
HANDLE hilo=CreateThread(NULL,0,hijo,NULL,0,NULL);
WaitForSingleObject(hilo,INFINITE);
CloseHandle(hilo);
return 0;
}

Informtica Industrial. Grado en Electrnica Industrial y Automtica


Departamento de Sistemas Informticos- UCLM

Programando con hilos en Windows

Creacin de mltiples hilos en Windows

Tambin podemos definir mltiples hilos a la vez utilizando un vector de hilos. Cada una de las
posiciones del vector contendr el HANDLE o identificador del hilo correspondiente.

Existe una instruccin que nos permite esperar hasta un mximo de 64 hilos a la vez, es la funcin
WaitForMultipleObjects(), cuyo prototipo es el siguiente:
DWORD WaitForMultipleObjects(
DWORD nCount,
CONST HANDLE *lpHandles,
BOOL fWaitAll, // espera uno o todos
DWORD dwMilliseconds);

Si queremos esperar a todos los hilos de un vector de hilos, fijaremos el valor de fWaitAll a
TRUE. Si fijamos el valor de dicha variable a FALSE, solamente esperaremos a que finalice uno
de ellos.

Especificando INFINITE en el parmetro dwMilliseconds, esperaremos de forma indefinida a que


los hilos hijos finalicen.

Informtica Industrial. Grado en Electrnica Industrial y Automtica


Departamento de Sistemas Informticos- UCLM

Programando con hilos en Windows

Mltiples hilos mediante vector de hilos


#include <stdio.h>
#include <windows.h>
DWORD WINAPI hijo(LPVOID arg){
printf("Hola!! Soy un hijo\n");
return 0;
}
int main (void){
HANDLE hilos[10];
int i;
for(i=0;i<10;i++){
hilos[i]=CreateThread(NULL,0,hijo,NULL,0,NULL);
}
WaitForMultipleObjects(10,hilos,TRUE,INFINITE);
for(i=0;i<10;i++){
CloseHandle(hilos[i]);
}
return 0;
}

Informtica Industrial. Grado en Electrnica Industrial y Automtica


Departamento de Sistemas Informticos- UCLM

10

Programando con hilos en Windows

Paso de parmetros a un hilo

Podemos modificar el ejemplo previo para, por ejemplo, enviar el nmero de hilo que se le ha sido
asignado a cada uno de ellos. Cmo? Empleando uno de los campos disponibles para ello dentro
de la funcin CreateThread(); concretamente el cuarto parmetro.

Qu ocurre si ejecutamos el siguiente programa? Por qu es incorrecto?


#include <stdio.h>
#include <windows.h>
DWORD WINAPI hijo(LPVOID pArg){
int *p=(int *)pArg;
printf("Hola!! Soy el hijo %d\n",*p);
return 0;
}
int main (void){
HANDLE hilos[10];
int i;
for(i=0;i<10;i++){
hilos[i]=CreateThread(NULL,0,hijo,&i,0,NULL);
}
WaitForMultipleObjects(10,hilos,TRUE,INFINITE);
for(i=0;i<10;i++){
CloseHandle(hilos[i]);
}
return 0;
}

Informtica Industrial. Grado en Electrnica Industrial y Automtica


Departamento de Sistemas Informticos- UCLM

11

Programando con hilos en Windows

Paso de parmetros a un hilo de forma correcta


#include <stdio.h>
#include <windows.h>
DWORD WINAPI hijo(LPVOID pArg){
int *p=(int *)pArg;
printf("Hola!! Soy el hijo %d\n",*p);
return 0;
}
int main (void){
HANDLE hilos[10];
int pDataArray[10];
int i;
for(i=0;i<10;i++){
pDataArray[i]=i;
hilos[i]=CreateThread(NULL,0,hijo,&pDataArray[i],0,NULL);
}
WaitForMultipleObjects(10,hilos,TRUE,INFINITE);
for(i=0;i<10;i++){
CloseHandle(hilos[i]);
}
return 0;
}

Informtica Industrial. Grado en Electrnica Industrial y Automtica


Departamento de Sistemas Informticos- UCLM

12

Programando con hilos en Windows

Seccin crtica en Windows

Entendemos por seccin crtica, en un programa, al conjunto de instrucciones en el cual se accede


a un recurso compartido (en nuestro caso, a una variable compartida) que no debe ser accedido por
ms de un proceso o hilo en ejecucin simultneamente. La seccin crtica terminar en un tiempo
determinado y el hilo slo tendr que esperar un perodo determinado de tiempo para poder entrar
a ella. En C++ las secciones crticas se declaran como variables globales (podemos tener ms de
una seccin crtica, adems de que deben ser inicializadas en el programa o funcin principal):
CRITICAL_SECTION cs;
InitializeCriticalSection(&cs); // DeleteCriticalSection(&cs);

Hasta ahora, la ejecucin de los hilos era asncrona, pues no podamos determinar qu hilo se
estaba ejecutando en cada instante. Con este mecanismo de sincronizacin, que controla la entrada
y salida de la seccin crtica, aseguramos la utilizacin en exclusiva del recurso: la variable
compartida. Nota: El hilo que obtiene el acceso a la seccin crtica debe ser quien la libere.

Entrada a la seccin crtica: EnterCriticalSection(&cs);

Salida de la seccin critica: LeaveCriticalSection(&cs);

Informtica Industrial. Grado en Electrnica Industrial y Automtica


Departamento de Sistemas Informticos- UCLM

13

Programando con hilos en Windows

Seccin crtica en Windows


#include <stdio.h>
#include <windows.h>
CRITICAL_SECTION cs;
int v_global=0;
DWORD WINAPI hijo(LPVOID arg){
EnterCriticalSection(&cs);
v_global=v_global+1; //Los hijos acceden de manera ordenada
LeaveCriticalSection(&cs);
return 0;
}
int main (void){
HANDLE hilos[10];
int i;
InitializeCriticalSection(&cs);
for(i=0;i<10;i++){
hilos[i]=CreateThread(NULL,0,hijo,NULL,0,NULL);
}
WaitForMultipleObjects(10,hilos,TRUE,INFINITE);
for(i=0;i<10;i++){
CloseHandle(hilos[i]);
}
DeleteCriticalSection(&cs);
printf("Total: %d\n",v_global);
return 0;
}

Informtica Industrial. Grado en Electrnica Industrial y Automtica


Departamento de Sistemas Informticos- UCLM

14

Programando con hilos en Windows

Finalizacin de hilos en Windows

Si queremos ejecutar de manera infinita un hilo podramos escribir el siguiente cdigo para ello:
DWORD WINAPI hijo(LPVOID arg){
while(1){
//do something
}
return 0;
}

Sin embargo, cmo podemos finalizar la ejecucin de dicho hilo? En este caso, utilizaremos una
variable global compartida, de forma que, sea el padre de dicho hilo el que realmente controle
cundo debe de finalizar la ejecucin del mismo. Inicializando dicha variable a 1, tendremos el
mismo efecto que con el cdigo anterior. Recordemos que, el padre tambin sigue ejecutndose,
por lo que podremos modificar el valor de variable de control cuando sea necesario.
int control=1;//variable global compartida
DWORD WINAPI hijo(LPVOID arg){
while(control){
//do something
}
return 0;
}

Informtica Industrial. Grado en Electrnica Industrial y Automtica


Departamento de Sistemas Informticos- UCLM

15

Programando con hilos en Windows

Finalizacin de hilos en Windows (instruccin de emergencia)

Aun cuando se desaconseja el uso de la finalizacin forzosa de un hilo, existe una instruccin que
nos permite forzar dicha finalizacin, su prototipo en el lenguaje de programacin C++ es el
siguiente:
WINAPI TerminateThread(
HANDLE hHandle,
DWORD dwExitCode);

Esta funcin solamente debe ser usada en situaciones especiales, y teniendo en cuenta que la
interrupcin en la ejecucin de un hilo se llevar a cabo en cualquier punto del cdigo de ste. Por
citar algunos ejemplos, los problemas en los que podramos incurrir incluyen:

La no liberacin de una seccin crtica.

La no liberacin de la memoria empleada para la declaracin de variables, incluida la reserva de memoria


dinmica que pudiera haberse realizado.

Si el hilo estaba haciendo uso de llamadas especficas al sistema operativo o a un librera auxiliar (por
ejemplo, para el acceso a un perifrico), las consecuencias pueden ser imprevisibles.

Informtica Industrial. Grado en Electrnica Industrial y Automtica


Departamento de Sistemas Informticos- UCLM

16

TEMA 10:
SISTEMAS OPERATIVOS
Y TIEMPO REAL

Bibliografa:

Informtica Industrial. Grado en Electrnica Industrial y Automtica


Departamento de Sistemas Informticos- UCLM

También podría gustarte