Documente Academic
Documente Profesional
Documente Cultură
1. OBJETIVO:
2. FUNDAMENTO TERICO:
Hilos (Threads)
Segn (Perez Campanero, 2002) para aprovechar al mximo las capacidades de los
ordenadores multiprocesador, algunos sistemas operativos, y tambin algunos lenguajes de
programacin, permiten a un programa dividirse en varias ramas que se pueden ejecutar en
paralelo. Estas ramas se conocen como hilos o threads.
Cada uno de los hilos se puede ejecutar en un procesador distinto, por lo que se acelera la
ejecucin del programa.
Estos hilos se pueden ejecutar en un procesador distinto, por lo que se acelera la ejecucin del
programa.
Estos hilos podemos considerarlos como procesos dbiles o procesos ligeros. En realidad
forman parte del mismo proceso que ejecuta el programa, pero a su vez, cada hilo tiene asociada
una estructura de datos similar al Bloque de Control de Proceso, que queda dentro de dicho
PCB.
Los hilos heredan el entorno del proceso, y pueden trabajar con l. Igualmente, al crearse el hilo,
se crea la estructura de datos correspondiente, y cuando desaparece el hilo, desaparece dicha
estructura. Al crearse el Bloque de Control del Hilo (TCB), se asigna memoria para la parte de
cdigo del programa que se identifica con dicho hilo.
Segn (Martinez Moreno, 2015) un proceso ligero, o thread, es un programa en ejecucin (flujo
de ejecucin) que comparte la imagen de memoria y otras informaciones con otros procesos
ligeros. Como muestra la Figura, un proceso puede contener un solo flujo de ejecucin, como
ocurre en los procesos clsicos, o ms de un flujo de ejecucin (procesos ligeros).
Desde el punto de vista de la programacin, un proceso ligero se define como una funcin cuya
ejecucin se puede lanzar en paralelo con otras. El hilo de ejecucin primario, o proceso ligero
primario, corresponde a la funcin 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 ejecucin,
pudindose 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 informacin del mismo. En
concreto, comparten:
Espacio de memoria.
Variables globales.
Archivos abiertos.
Procesos hijos.
Temporizadores.
Seales y semforos.
Contabilidad.
Es importante destacar que todos los procesos ligeros de un mismo proceso comparten el mismo
espacio de direcciones de memoria, que incluye el cdigo, los datos y las pilas de los diferentes
procesos ligeros. Esto hace que no exista proteccin de memoria entre los procesos ligeros de
un mismo proceso, algo que si ocurre con los procesos convencionales.
El proceso ligero constituye la unidad ejecutable en Windows NT. La Figura representa de forma
esquemtica la estructura de un proceso de Windows NT con sus procesos ligeros.
P g i n a 2 | 11
son escritos por el proceso anterior. De esta manera el planificador de corto plazo va a dar el
uso de la CPU a cada proceso a medida que pueda ejecutarse minimizando los tiempos muertos.
Para mejorar el rendimiento, la mayora de los sistemas operativos implementan las tuberas
usando buffers, lo que permite al proceso proveedor generar ms datos que lo que el proceso
consumidor puede atender inmediatamente.
Podemos distinguir dos tipos de tuberas:
Tubera sin nombre
Las tuberas sin nombre tienen asociado un fichero en memoria principal, por lo tanto, son
temporales y se eliminan cuando no estn siendo usados ni por productores ni por consumidores.
Permiten la comunicacin entre el proceso que crea un cauce y procesos hijos tras la creacin
de la tubera.
Tubera con nombre
Su diferencia respecto a las tuberas sin nombre radica en que el cauce se crea en el sistema de
archivos, y por lo tanto no tienen carcter temporal. Se manejan mediante llamadas al
sistema (open, close, read y write) como el resto de ficheros del sistema. Permiten la
comunicacin entre los procesos que usen dicha tubera, aunque no exista una conexin
jerrquica entre ellos.
3. PROCEDIMIENTO
Abrir la terminal de Linux y como en el anterior informe crear un fichero en ejecutar el cdigo en
C++
Ejemplo01.c
#include<stdio.h>
#include<pthread.h>
#include<stdlib.h>
#include<unistd.h>
void *hilo1(void *arg)
{
int i;
for(i=0;i<10;i++)
{
printf("Mensaje Generado Hilo1\n");
}
return(NULL);
}
int main(void)
{
pthread_t mihilo;
int i;
printf("Esperando finalizacion de hilos\n");
if(pthread_create(&mihilo,NULL,hilo1,NULL))
{
printf("Mensaje Generado por Main\n");
abort();
}
P g i n a 3 | 11
for(i=0;i<10;i++)
{
printf("Mensaje Generado por Main\n");
}
if(pthread_join(mihilo,NULL))
{
printf("Error esperando finalizacion de hilos");
abort();
}
printf("Fin de ejecucin de hilos\n");
exit(0);
Interpretacin:
En la funcin main se ha declarado la variable mihilo, que es del tipo pthread_t (definido en la
librera pthread.h). El tipo pthread_t es llamado id del hilo y es usado como una especie de
identificador o manejador (thread). Seguidamente llamamos a la funcin pthread_create que como
su nombre indica creara un hilo. La funcin pthread_create dentro de un if() debido a que esta
funcin devuelve un cero si el hilo fue creado exitosamente y un valor diferente de cero si fallo.
Asi detectamos si fallo o no. El primer argumento de la funcin es un puntero a la variable
&mihilo. El segundo es NULL. El tercer argumento se ejecutara cuando la funcin nuevo hilo
empieze, retornara algn valor cuando este termine. Este programa consiste en dos hilo ya que la
funcin main tambin se considera como un hilo. Al ejecutar la lnea pthread_join une los hilos
(threads) en uno solo.
Ejemplo02.c
#include<stdio.h>
#include<pthread.h>
#include<stdlib.h>
P g i n a 4 | 11
#include<unistd.h>
void *hilo1(void *arg)
{
int i;
for(i=0;i<10;i++)
{
printf("Mensaje Hilo #1\n");
}
return(NULL);
}
void *hilo2(void *arg)
{
int i;
for(i=0;i<10;i++)
{
printf("Mensaje Hilo #2\n");
sleep(1);
}
return(NULL);
}
void *hilo3(void *arg)
{
int i;
for(i=0;i<10;i++)
{
printf("Mensaje Hilo #3\n");
sleep(1);
}
return(NULL);
}
int main(void)
{
pthread_t mihilo_1;
pthread_t mihilo_2;
pthread_t mihilo_3;
if(pthread_create(&mihilo_1,NULL,hilo1,NULL))
{
printf("Error creando hilo1");
abort();
}
if(pthread_create(&mihilo_2,NULL,hilo2,NULL))
{
printf("Error creando hilo2");
abort();
}
if(pthread_create(&mihilo_3,NULL,hilo3,NULL))
{
printf("Error creando hilo3");
abort();
}
printf("Esperando finalizacion de hilos\n");
int i;
for(i=0;i<10;i++)
{
P g i n a 5 | 11
P g i n a 6 | 11
Interpretacin:
En la funcin main se ha declarado la variable mihilo_1, mihilo_2 y mihilo_3; son del tipo pthread_t
(definido en la librera pthread.h). El tipo pthread_t es llamado id del hilo y es usado como una
especie de identificador o manejador (thread). Seguidamente llamamos a la funcin
pthread_create que como su nombre indica creara un hilo. La funcin pthread_create dentro de
un if() debido a que esta funcin devuelve un cero si el hilo fue creado exitosamente y un valor
diferente de cero si fallo. Asi detectamos si fallo o no.
El primer argumento de la funcin es un puntero a la variable &mihilo_1. El segundo es NULL. El
tercer argumento se ejecutara cuando la funcin nuevo hilo empieze, retornara algn valor cuando
este termine seguir el mismo paso con el hilo_2 y el hilo_3. Este programa consiste en cuatro
hilos ya que la funcin main tambin se considera como un hilo. Al ejecutar la lnea pthread_join
une los hilos (threads) en uno solo.
Tuberia01.c
#include<stdio.h>
#include<pthread.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#define LEER 0
#define ESCRIBIR 1
int main()
{
int descr[2]; /*Descriptores de E y S de la tuberia */
int bytesleidos;
char mensaje[100], *frase="Hola mundo";
printf("**Ejemplo de comunicacion de padre e hijo**\n\n");
pipe(descr);
if(fork()==0)
{
/*Seccion hijo*/
P g i n a 7 | 11
close(descr[LEER]);
write(descr[ESCRIBIR],frase,strlen(frase));
close(descr[ESCRIBIR]);
}
else
{
/*Seccion padre*/
close(descr[ESCRIBIR]);
bytesleidos=read(descr[LEER],mensaje,100);
mensaje[bytesleidos]='\0';
printf("Bytes leidos: %d\n",bytesleidos);
printf("Mensaje enviado por el hijo: %s\n",mensaje);
close(descr[LEER]);
}
}
Interpretacin:
En las tuberas sin nombre o PIPES sin nombre solo se puede mandar mensaje entre procesos
emparentados. El siguiente programa muestra un proceso padre se puede comunicar con su hijo
haciendo uso de tuberas sin nombre, el proceso padre le proporciona una cadena al proceso hijo
y este lo imprimir en pantalla.
productor.c
/*productor*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include<string.h>
P g i n a 8 | 11
consumidor.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(){
char mensaje[100], *nfifo="fifo";
int fd; /*file descriptor*/
printf("consumidor\n\n");
/*leendo en la tuberia (consumidor)*/
fd=open(nfifo, O_RDONLY);
if(fd==-1)
perror("error al abrir la tuberia (lectura)\n");
else{
/*lectura de la tuberia*/
read(fd, mensaje, 100);
printf("consumidor recibio: %s\n", mensaje);
close(fd);
}
P g i n a 9 | 11
/*eliminando tuberia*/
unlink(nfifo);
}
La siguiente captura de pantalla muestra la salida de la ejecucin del productor y consumidor.
Interpretacin:
El productor mandara un mensaje de texto el cual ser almacenado en la tubera, luego el
consumidor recobrara ese mensaje para desplegarlo en la pantalla.
4. ANEXOS:
01 nano ejemplo01.c
02 gcc ejemplo01.c -o ejemplo01 -pthread
03 ./ejemplo01
04 nano ejemplo02.c
05 gcc ejemplo02.c -o ejemplo02 -pthread
06 ./ejemplo02
07 gcc ejemplo02.c -o ejemplo02 -pthread
08 ./ejemplo02
09 nano tuberia01.c
10 gcc tuberia01.c -o tuberia01 -pthread
11 ./tuberia01
12 nano productor.c
13 gcc productor.c -o productor -pthread
14 nano productor.c
P g i n a 10 | 11
5. CONCLUSIONES:
6. BIBLIOGRAFIA:
P g i n a 11 | 11