SlideShare una empresa de Scribd logo
1 de 9
Descargar para leer sin conexión
Practica 2. Creación de procesos e hilos
1. Objetivos
1).-Que el alumno aprenda a crear procesos y a controlar la estructura jerár-
quica resultante con las llamadas al sistema fork, getpid, getppid, wait y exit.
2).-Que el alumno aprenda a gestionar hilos con la biblioteca de funciones
pthread (POSIX Threads).
2. Introducción
2.1. Creación de proceso con fork.
Un proceso es cualquier programa o comando en ejecución con un identifica-
dor de proceso o pid asignado por el sistema y que está en alguno de los siguientes
estados: Running (R), Sleeping (S), Waiting (D), Stopped (T) o Zombie (Z). To-
dos los procesos, exepto el proceso init cuyo pid es 1, tienen un proceso creador
al cual llamamos su proceso padre. Una llamada al sistema para crear procesos en
Linux es fork() y su declaración es:
#include <unistd.h>
#include <sys/types.h>
pid_t fork(void);
Después de la invocación de fork() se crea un proceso hijo con el mismo
código que el proceso padre y una copia de sus datos (variables y valores). El
proceso padre recibe como valor de retorno un entero positivo que corresponde
al pid de su hijo y el proceso hijo recibe como valor de retorno 0, este valor
se pude utilizar para controlar las instrucciones que debe ejecutar cada proceso.
Por otro lado, fork() regresa -1 si el proceso hijo no se puede crear. Ambos
procesos continúa con la ejecución del programa a partir del fork() de manera
concurrente. Ambos procesos comparten los archivos abiertos pero cada uno tiene
1
su propio contador de programa. Adicionalmente, las funciones getpid() y
getppid() regresan el pid y el ppid (pid del proceso padre) de quien las invoca,
su declaración es:
#include <unistd.h>
pid_t getpid(void);
pid_t getppid(void);
Ejemplo 1.
/*
* $ gcc 1fork.c -o fork
* $ ./fork
*
* Después de invocar fork(): El proceso hijo incrementa en uno
*sus variables y escribe el resultado en el archivo salida.txt, el proceso
*padre incrementa en dos sus variables y escribe el resultado en el archivo
*salida.txt, ambos procesos imprimen el contenido del archivo.
*
*Cada proceso maneja sus variables de forma independiente aun siendo globales.
*Los dos procesos tienen acceso concurrente al archivo, cada proceso cierra el
archivo para sí mismo.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int x=1; //variable global
int main()
{
pid_t ret;
FILE *apArch;
int y=2; //variable local
if( (apArch=fopen("salida.txt","w")) == NULL ){
printf("Error al abrir archivon");
exit(0);
}
ret=fork();
switch(ret){
case -1:printf("No se pude crear un proceso hijo.n");
break;
case 0: x=x+1;
y=y+1;
fprintf(apArch,"soy el proceso hijo pid: %d, pidPadre: %d, x= %d,y
= %dn",getpid(),getppid(),x,y);
fclose(apArch);
break;
default:x=x+2;
y=y+2;
2
fprintf(apArch,"soy el proceso padre pid: %d, pidHijo: %d, x= %d,y
= %dn",getpid(),ret,x,y);
fclose(apArch);
}
system("cat ./salida.txt"); //Muestra el contenido del archivo
//lo hacen los dos procesos.
return 1;
}
Compilación y ejecución
$ gcc 1fork.c -o fork
$ ./fork
soy el proceso padre pid:17275, pidHijo: 17276, x=3,y=4
soy el proceso hijo pid:17276, pidPadre: 17275, x=2,y=3
soy el proceso padre pid:17275, pidHijo: 17276, x=3,y=4
soy el proceso hijo pid:17276, pidPadre: 17275, x=2,y=3
2.2. Comunicación mediante wait y exit.
Después de una invocación a fork() el proceso padre puede esperar la ter-
minación de su hijo con la función wait() y su hijo puede avisarle a su padre
que ya terminó con la función exit(), su declaración es:
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
pid_t wait(int *status);
void exit(int st);
exit() termina el proceso que la invoca y le regresa el valor de st al sistema
quien lo almacena en status. wait() bloquea la ejecución del proceso padre
hasta que alguno de sus procesos hijos invoca exit(). wait() regresa el pid
del proceso que invocó exit() y continúa ejecutándose, dos de las macros que
se pueden utilizar para evaluar el contenido de status son:
WIFEXITED(status) Distinto de cero si el hijo terminó normalmente.
WEXITSTATUS(status) Evalúa los ocho bits menos significativos del
código de retorno del hijo, puede ser el argumento de exit() o de return(),
es decir st.
3
Ejemplo 2 y 3
Descargar el .zip de moodle.
Compilación y ejecución
$ gcc 2fork.c -o fork
$ ./fork
$ ps -eo pid,user,comm|grep fork|head -n 1|awk ’{print $1}’|xargs pstree -cp
$ gcc 3fork.c -o fork
$ ./fork
$ ps -eo pid,user,comm|grep fork|head -n 1|awk ’{print $1}’|xargs pstree -cp
2.3. Hilos POSIX
POSIX Threads (Portable Operating System Interface Threads) es una biblio-
teca de funciones proporcionada por los sistemas operativos tipo UNIX para la
gestión de hilos. Para trabajar con hilos POSIX es necesario incluir la biblioteca
de funciones pthread.h en el encabezado de los programas en lenguaje C y
compilar con la opción lpthread. Algunas de sus funciones son:
#include <pthread.h>
int pthread_create(pthread_t *tid, const pthread_attr_t
*attr, (void *)(*star_routine)(void *), void *arg);
void pthread_exit(void *value_ptr);
int pthread_join(pthread_t thread, void **value_ptr);
La función pthread_create sirve para crear hilos, regresa 0 si tuvo éxito
y un valor de error en caso contrario, sus argumentos deben ser:
tid Un apuntador a la variable donde se almacenará el identificador del
hilo, si es que la llamada tuvo éxito.
attr Es un apuntador a la variable donde se almacenan los atributos que
el sistema debe asignar al hilo. Si es igual a NULL, tendrá los atributos por
omisión.
(*star_routine) Es una referencia a la función que el hilo ejecuta
cuando es creado. La función devuelve un apuntador sin tipo (void *) y
su único argumento es un apuntador sin tipo (void *). Para poder utilizar
un argumento de otro tipo se debe hacer un cast al recuperar el valor.
4
arg Es el argumento que se le pasa a la función star_routine().
La función pthread_exit termina el hilo que la invoca. El valor del argu-
mento value_ptr queda disponible para pthread_join si la primera tuvo
éxito. value_ptr debe apuntar a datos que existan después de que el hilo ter-
mine.
La función pthread_join suspende la ejecución del hilo que la invoca has-
ta que el hilo identificado con thread termine, ya sea porque llamó a pthread_exit
o por que fue cancelado. Si value_ptr no es NULL, entonces el valor retornado
por thread es almacenado en la ubicación apuntado por value_ptr.
Ejemplo 4.
El hilo principal crea dos hilos y espera a que termine su ejecución, cada uno
ejecuta la función ejecutaHilo() con la cual imprime un mensaje y termina,
cada hilo se ejecuta a su propia velocidad. Las variables h1 y h2 son referencias
a los hilos, asignadas por posix.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
void ejecutaHilo();
void main()
{
pthread_t h1,h2;
pthread_create(&h1,NULL,(void *)&ejecutaHilo,NULL);
pthread_create(&h2,NULL,(void *)&ejecutaHilo,NULL);
pthread_join(h1,NULL);
pthread_join(h2,NULL);
}
void ejecutaHilo()
{
printf("Hilo en ejecución...n");
sleep(5);
pthread_exit(NULL);
}
Compilación y ejecución
$ gcc ejemplo1.c -lpthread
$ ./a.out
Hilo en ejecución...
Hilo en ejecución...
5
Mientras se está ejecutando, hacer lo siguiente en otra terminal:
$ ps -eo pid,user,comm|grep a.out|head -n 1|awk ’{print $1}’|xargs pstree -cp
a.out(4411)-----{a.out}(4412)
|--{a.out}(4413)
Ejemplo 5.
La biblioteca de funciones pthread.h le asigna a cada hilo un identificador
que se guarda en tid, y se puede obtener con la función pthread_self(). Por
otro lado Linux también le asigna un identificador a cada hilo, el cual se puede
obtener con la llamada al sistema SYS_gettid que no pertenece a C. Además
los hilos pueden ser nombrados por los argumentos de la función que ejecutan.
Lo anterior se muestra en el siguiente código.El hilo principal crea dos hilos,
cada uno ejecuta la función ejecutaHilo() que recibe un id asignado por el
programa, el hilo imprime dicho identificador junto con los identificadores asig-
nados por posix y por Linux.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <syscall.h>
void ejecutaHilo(void *id);
void main()
{
pthread_t h1,h2;
int id1=10, id2=20;
pthread_create(&h1,NULL,(void *)&ejecutaHilo,(void *)&id1);
printf("hilo1( %u) creadon",(unsigned int)h1);
pthread_create(&h2,NULL,(void *)&ejecutaHilo,(void *)&id2);
printf("hilo2( %u) creadon",(unsigned int)h2);
pthread_join(h1,NULL);
pthread_join(h2,NULL);
}
void ejecutaHilo(void *id)
{
int *idh=(int *)(id);
int tid=syscall(SYS_gettid);//LLamada al sistema explícita, para obtener el
id de Linux
printf("Hilo en ejecución con idPosix= %u, idLinux= %d, idPrograma= %dn",(int)
pthread_self(),tid,*idh);
sleep(7);
pthread_exit(NULL);
}
6
Compilación y ejecución
$ gcc ejemplo2.c -o -lpthread
$ ./a.out
hilo1(2075494144) creado
Hilo en ejecución con idPosix=2075494144, idLinux=4262, idPrograma=10
hilo2(2067101440) creado
Hilo en ejecución con idPosix=2067101440, idLinux=4263, idPrograma=20
Mientras se está ejecutando, hacer lo siguiente en otra terminal:
$ ps -eo pid,user,comm|grep a.out|head -n 1|awk ’{print $1}’|xargs pstree -cp
a.out(4411)-----{a.out}(4412)
|--{a.out}(4413)
Ejemplo 6.
Notar el uso de pthread_join y pthread_exit.
Notar que se pude hacer referencia al id asignado por posix con h1 y h2,
sin necesidad de utilizar pthread_self()
Es decir, que los hilos se pueden gestionar con el id asignado por posix (h1
y h2), sin necesidad de conocer el id asignado por Linux.
Notar que comparten memoria: Pueden leer las variables globales y las re-
ferencias a memoria (apuntadores) son sobre un espacio de memoria com-
partido.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
int varGlobal = 1000; //compartida por los hilos.
void ejecutaHilo(void *id); //ejecutada por los hilos.
void main()
{
pthread_t h1,h2; //id posix para los hilos
int v1=5, v2=6; //argumentos para la función que ejecutan los hilos
int *r1=NULL; //para guardar el valor de exit y leerlo con join
int i;
pthread_create(&h1,NULL,(void *)&ejecutaHilo,(void *)&v1);
pthread_create(&h2,NULL,(void *)&ejecutaHilo,(void *)&v2);
for(i=0;i<10;i++){
printf("Hilo principal, varGlobal= %dn",varGlobal+=1);
sleep(1);
}
7
pthread_join(h1,(void **)&r1);
printf("hilo1 termina con: %dn",*r1);
pthread_join(h2,(void **)&r1);
printf("hilo2 termina con: %dn",*r1);
}
void ejecutaHilo(void *v)
{
int *vh=(int *)(v);
sleep(*vh); //utiliza el argumento recibido.
printf("Hilo que recibe %d, espera %ds, imprime varGlobal= %d, modifca val
recibidon",*vh,*vh,varGlobal);
*vh=5*(*vh); //modifica el argumento recibido.
pthread_exit(vh); //termina y deja vh para el join.
}
Compilación y ejecución
$ gcc ejemplo3.c -lpthread
$ ./a.out
Hilo principal, varGlobal=1001
Hilo principal, varGlobal=1002
Hilo principal, varGlobal=1003
Hilo principal, varGlobal=1004
Hilo principal, varGlobal=1005
Hilo que recibe 5, espera 5s, imprime varGlobal=1005, modifca val recibido
Hilo principal, varGlobal=1006
Hilo que recibe 6, espera 6s, imprime varGlobal=1006, modifca val recibido
Hilo principal, varGlobal=1007
Hilo principal, varGlobal=1008
Hilo principal, varGlobal=1009
Hilo principal, varGlobal=1010
hilo1 termina con: 25
hilo2 termina con: 30
Mientras se está ejecutando, hacer lo siguiente en otra terminal:
$ ps -eo pid,user,comm|grep ej1hilos|head -n 1|awk ’{print $1}’|xargs pstree -cp
a.out(4736)-----{a.out}(4737)
|--{a.out}(4738)
8
3. Actividades.
1. Construir un árbol binario de procesos de altura N. Hacer que N sea gene-
rado aleatoriamente y que el nodo raíz imprima el número total de hijos.
Utilizar sleep() para poder visualizar el árbol con el comando visto en los
ejercicios.
NOTA. No utilizar recursividad.
2. Modificar el ejemplo cuatro para que cada hilo genere dos hilos más y es-
pere su finalización. Explicar qué es lo que pasa ¿Quién es el padre de los
nuevos hilos? Mostrar el árbol de procesos (hilos).
3. Modificar el ejemplo uno para que un hilo clone al proceso con fork(). Ex-
plicar qué es lo que pasa ¿También se clonan los hilos? Mostrar el árbol de
procesos (hilos).
4. Después de haber ejecutado el fork() del punto anterior. Dado que todos los
hilos comparten los recursos del proceso al que pertenecen ¿Es posible que
un hilo sepa a qué proceso pertenece? En caso afirmativo ¿Cómo?
5. Modificar el ejemplo tres para que genere N hilos y los guarde en un arreglo.
Cada hilo debe ejecutar la función ejecutaHilo recibiendo como argu-
mento la localidad (i) donde se encuentra el hilo, el hilo debe escribir su va-
lor i en la variable global y salir con pthread_exit(). El hilo principal
debe esperar por cada uno de los hilos con la función pthread_join().
N debe ser definido en el programa o dado por el usuario. Asegurarse de que
los hilos se ejecuten concurrentemente, es decir, no serializar la ejecución
con sleep u otro código.
6. ¿Cuál es el valor que se espera que tenga la variable global? y ¿Por qué?
7. Hacer que cada hilo del programa anterior, además de su identificador (i),
imprima quien es su vecino posterior (i+1) y anterior (i-1), suponiendo que
el arreglo es circular. Notar que no es necesaria la comunicación entre hilos,
cada hilo debe calcular i-1 e i+1 a partir de i.
9

Más contenido relacionado

La actualidad más candente

Concurrencia y nuevas características en C++11
Concurrencia y nuevas características en C++11Concurrencia y nuevas características en C++11
Concurrencia y nuevas características en C++11Sebastián Vizcay
 
Realidad Aumentada 01 documentacion tapir
Realidad Aumentada 01 documentacion tapirRealidad Aumentada 01 documentacion tapir
Realidad Aumentada 01 documentacion tapirAgustín Hv
 
Clase 02 gestion de puertos - directivas
Clase 02   gestion de puertos - directivasClase 02   gestion de puertos - directivas
Clase 02 gestion de puertos - directivasalmidon_pcb
 
Roger1 libreria
Roger1 libreria Roger1 libreria
Roger1 libreria Urmom2
 
Informe tecnico u4 final
Informe tecnico u4 finalInforme tecnico u4 final
Informe tecnico u4 finalIrving Che
 
Estructura basica de_un_programa_c_
Estructura basica de_un_programa_c_Estructura basica de_un_programa_c_
Estructura basica de_un_programa_c_Maztherprozh
 
Understanding Advanced Buffer Overflow
Understanding Advanced Buffer OverflowUnderstanding Advanced Buffer Overflow
Understanding Advanced Buffer OverflowConferencias FIST
 
Parcial I de Sistema de Operación – Semestre 201415
Parcial I de Sistema de Operación – Semestre 201415Parcial I de Sistema de Operación – Semestre 201415
Parcial I de Sistema de Operación – Semestre 201415Viviana Trujillo
 
Compilador divisor de cantidades con Jflex y Cup
Compilador divisor de cantidades con Jflex y CupCompilador divisor de cantidades con Jflex y Cup
Compilador divisor de cantidades con Jflex y CupSoraya Lara
 
Programación C++
Programación C++Programación C++
Programación C++Juan Islas
 

La actualidad más candente (18)

Concurrencia y nuevas características en C++11
Concurrencia y nuevas características en C++11Concurrencia y nuevas características en C++11
Concurrencia y nuevas características en C++11
 
Realidad Aumentada 01 documentacion tapir
Realidad Aumentada 01 documentacion tapirRealidad Aumentada 01 documentacion tapir
Realidad Aumentada 01 documentacion tapir
 
Clase 02 gestion de puertos - directivas
Clase 02   gestion de puertos - directivasClase 02   gestion de puertos - directivas
Clase 02 gestion de puertos - directivas
 
C++
C++C++
C++
 
Programación en c++
Programación en c++Programación en c++
Programación en c++
 
Python para todos
Python para todosPython para todos
Python para todos
 
Semana 7 Proyecto Misión TIC 2022
Semana 7 Proyecto Misión TIC 2022Semana 7 Proyecto Misión TIC 2022
Semana 7 Proyecto Misión TIC 2022
 
TUTORIAL JAVA
TUTORIAL JAVATUTORIAL JAVA
TUTORIAL JAVA
 
Presentacion Python
Presentacion  Python Presentacion  Python
Presentacion Python
 
Roger1 libreria
Roger1 libreria Roger1 libreria
Roger1 libreria
 
Viernes Tecnicos DTrace
Viernes Tecnicos DTraceViernes Tecnicos DTrace
Viernes Tecnicos DTrace
 
Informe tecnico u4 final
Informe tecnico u4 finalInforme tecnico u4 final
Informe tecnico u4 final
 
Estructura basica de_un_programa_c_
Estructura basica de_un_programa_c_Estructura basica de_un_programa_c_
Estructura basica de_un_programa_c_
 
Understanding Advanced Buffer Overflow
Understanding Advanced Buffer OverflowUnderstanding Advanced Buffer Overflow
Understanding Advanced Buffer Overflow
 
Parcial I de Sistema de Operación – Semestre 201415
Parcial I de Sistema de Operación – Semestre 201415Parcial I de Sistema de Operación – Semestre 201415
Parcial I de Sistema de Operación – Semestre 201415
 
02 - Tipos de datos escalares en Python 3
02 - Tipos de datos escalares en Python 302 - Tipos de datos escalares en Python 3
02 - Tipos de datos escalares en Python 3
 
Compilador divisor de cantidades con Jflex y Cup
Compilador divisor de cantidades con Jflex y CupCompilador divisor de cantidades con Jflex y Cup
Compilador divisor de cantidades con Jflex y Cup
 
Programación C++
Programación C++Programación C++
Programación C++
 

Similar a procesos

Lw2010 Pedro Valera
Lw2010 Pedro ValeraLw2010 Pedro Valera
Lw2010 Pedro Valeraguestf280e2
 
Lw2010 - Uso De La Programacion En Linux Para La Seguridad En Redes
Lw2010 - Uso De La Programacion En Linux Para La Seguridad En RedesLw2010 - Uso De La Programacion En Linux Para La Seguridad En Redes
Lw2010 - Uso De La Programacion En Linux Para La Seguridad En Redesguest5d7f33c
 
Construyendo rootkits basicos
Construyendo rootkits basicosConstruyendo rootkits basicos
Construyendo rootkits basicosTensor
 
Desarrollo de rootkits en Linux [GuadalajaraCON 2013]
Desarrollo de rootkits en Linux [GuadalajaraCON 2013]Desarrollo de rootkits en Linux [GuadalajaraCON 2013]
Desarrollo de rootkits en Linux [GuadalajaraCON 2013]Websec México, S.C.
 
Linux Kernel - System Calls - Modules - Drivers
Linux Kernel - System Calls - Modules - DriversLinux Kernel - System Calls - Modules - Drivers
Linux Kernel - System Calls - Modules - DriversMartin Baez
 
Ej1 t2 l3-1
Ej1 t2 l3-1Ej1 t2 l3-1
Ej1 t2 l3-1jvidalcc
 
Usando flex en Windows
Usando flex en WindowsUsando flex en Windows
Usando flex en WindowsMariano Rico
 
37 supervisión del sistema
37  supervisión del sistema37  supervisión del sistema
37 supervisión del sistemaAprende Viendo
 
Sistemas Distribuidos y Paralelismo - Unidad 2
Sistemas Distribuidos y Paralelismo - Unidad 2Sistemas Distribuidos y Paralelismo - Unidad 2
Sistemas Distribuidos y Paralelismo - Unidad 2ingnucious
 
Creacion de shellcodes para Exploits en Linux/x86
Creacion de shellcodes para Exploits en Linux/x86 Creacion de shellcodes para Exploits en Linux/x86
Creacion de shellcodes para Exploits en Linux/x86 Internet Security Auditors
 
Arduino: programación básica de Arduino
Arduino: programación básica de ArduinoArduino: programación básica de Arduino
Arduino: programación básica de ArduinoSANTIAGO PABLO ALBERTO
 

Similar a procesos (20)

Guia final so
Guia final soGuia final so
Guia final so
 
Lw2010 Pedro Valera
Lw2010 Pedro ValeraLw2010 Pedro Valera
Lw2010 Pedro Valera
 
Lw2010 - Uso De La Programacion En Linux Para La Seguridad En Redes
Lw2010 - Uso De La Programacion En Linux Para La Seguridad En RedesLw2010 - Uso De La Programacion En Linux Para La Seguridad En Redes
Lw2010 - Uso De La Programacion En Linux Para La Seguridad En Redes
 
Ejclase mpi
Ejclase mpiEjclase mpi
Ejclase mpi
 
Construyendo rootkits basicos
Construyendo rootkits basicosConstruyendo rootkits basicos
Construyendo rootkits basicos
 
Practica 5
Practica 5Practica 5
Practica 5
 
Desarrollo de rootkits en Linux [GuadalajaraCON 2013]
Desarrollo de rootkits en Linux [GuadalajaraCON 2013]Desarrollo de rootkits en Linux [GuadalajaraCON 2013]
Desarrollo de rootkits en Linux [GuadalajaraCON 2013]
 
Tutorial C++
Tutorial C++Tutorial C++
Tutorial C++
 
Linux Kernel - System Calls - Modules - Drivers
Linux Kernel - System Calls - Modules - DriversLinux Kernel - System Calls - Modules - Drivers
Linux Kernel - System Calls - Modules - Drivers
 
Ej1 t2 l3-1
Ej1 t2 l3-1Ej1 t2 l3-1
Ej1 t2 l3-1
 
Usando flex en Windows
Usando flex en WindowsUsando flex en Windows
Usando flex en Windows
 
Procesos
ProcesosProcesos
Procesos
 
37 supervisión del sistema
37  supervisión del sistema37  supervisión del sistema
37 supervisión del sistema
 
Procesos
ProcesosProcesos
Procesos
 
Procesos sistema computacional UNIX
Procesos sistema computacional UNIXProcesos sistema computacional UNIX
Procesos sistema computacional UNIX
 
Sistemas Distribuidos y Paralelismo - Unidad 2
Sistemas Distribuidos y Paralelismo - Unidad 2Sistemas Distribuidos y Paralelismo - Unidad 2
Sistemas Distribuidos y Paralelismo - Unidad 2
 
Manejo de memoria
Manejo de memoriaManejo de memoria
Manejo de memoria
 
Creacion de shellcodes para Exploits en Linux/x86
Creacion de shellcodes para Exploits en Linux/x86 Creacion de shellcodes para Exploits en Linux/x86
Creacion de shellcodes para Exploits en Linux/x86
 
Arduino: programación básica de Arduino
Arduino: programación básica de ArduinoArduino: programación básica de Arduino
Arduino: programación básica de Arduino
 
Cplus
CplusCplus
Cplus
 

Último

clases de dinamica ejercicios preuniversitarios.pdf
clases de dinamica ejercicios preuniversitarios.pdfclases de dinamica ejercicios preuniversitarios.pdf
clases de dinamica ejercicios preuniversitarios.pdfDanielaVelasquez553560
 
2. UPN PPT - SEMANA 02 GESTION DE PROYECTOS MG CHERYL QUEZADA(1).pdf
2. UPN PPT - SEMANA 02 GESTION DE PROYECTOS MG CHERYL QUEZADA(1).pdf2. UPN PPT - SEMANA 02 GESTION DE PROYECTOS MG CHERYL QUEZADA(1).pdf
2. UPN PPT - SEMANA 02 GESTION DE PROYECTOS MG CHERYL QUEZADA(1).pdfAnthonyTiclia
 
SOLICITUD-PARA-LOS-EGRESADOS-UNEFA-2022.
SOLICITUD-PARA-LOS-EGRESADOS-UNEFA-2022.SOLICITUD-PARA-LOS-EGRESADOS-UNEFA-2022.
SOLICITUD-PARA-LOS-EGRESADOS-UNEFA-2022.ariannytrading
 
ECONOMIA APLICADA SEMANA 555555555544.pdf
ECONOMIA APLICADA SEMANA 555555555544.pdfECONOMIA APLICADA SEMANA 555555555544.pdf
ECONOMIA APLICADA SEMANA 555555555544.pdfmatepura
 
Linealización de sistemas no lineales.pdf
Linealización de sistemas no lineales.pdfLinealización de sistemas no lineales.pdf
Linealización de sistemas no lineales.pdfrolandolazartep
 
Voladura Controlada Sobrexcavación (como se lleva a cabo una voladura)
Voladura Controlada  Sobrexcavación (como se lleva a cabo una voladura)Voladura Controlada  Sobrexcavación (como se lleva a cabo una voladura)
Voladura Controlada Sobrexcavación (como se lleva a cabo una voladura)ssuser563c56
 
SSOMA, seguridad y salud ocupacional. SST
SSOMA, seguridad y salud ocupacional. SSTSSOMA, seguridad y salud ocupacional. SST
SSOMA, seguridad y salud ocupacional. SSTGestorManpower
 
IPERC Y ATS - SEGURIDAD INDUSTRIAL PARA TODA EMPRESA
IPERC Y ATS - SEGURIDAD INDUSTRIAL PARA TODA EMPRESAIPERC Y ATS - SEGURIDAD INDUSTRIAL PARA TODA EMPRESA
IPERC Y ATS - SEGURIDAD INDUSTRIAL PARA TODA EMPRESAJAMESDIAZ55
 
Unidad 3 Administracion de inventarios.pptx
Unidad 3 Administracion de inventarios.pptxUnidad 3 Administracion de inventarios.pptx
Unidad 3 Administracion de inventarios.pptxEverardoRuiz8
 
¿QUE SON LOS AGENTES FISICOS Y QUE CUIDADOS TENER.pptx
¿QUE SON LOS AGENTES FISICOS Y QUE CUIDADOS TENER.pptx¿QUE SON LOS AGENTES FISICOS Y QUE CUIDADOS TENER.pptx
¿QUE SON LOS AGENTES FISICOS Y QUE CUIDADOS TENER.pptxguillermosantana15
 
Caldera Recuperadora de químicos en celulosa tipos y funcionamiento
Caldera Recuperadora de químicos en celulosa  tipos y funcionamientoCaldera Recuperadora de químicos en celulosa  tipos y funcionamiento
Caldera Recuperadora de químicos en celulosa tipos y funcionamientoRobertoAlejandroCast6
 
estadisticasII Metodo-de-la-gran-M.pdf
estadisticasII   Metodo-de-la-gran-M.pdfestadisticasII   Metodo-de-la-gran-M.pdf
estadisticasII Metodo-de-la-gran-M.pdfFlorenciopeaortiz
 
Diapositiva de Topografía Nivelación simple y compuesta
Diapositiva de Topografía Nivelación simple y compuestaDiapositiva de Topografía Nivelación simple y compuesta
Diapositiva de Topografía Nivelación simple y compuestajeffsalazarpuente
 
Reporte de Exportaciones de Fibra de alpaca
Reporte de Exportaciones de Fibra de alpacaReporte de Exportaciones de Fibra de alpaca
Reporte de Exportaciones de Fibra de alpacajeremiasnifla
 
Elaboración de la estructura del ADN y ARN en papel.pdf
Elaboración de la estructura del ADN y ARN en papel.pdfElaboración de la estructura del ADN y ARN en papel.pdf
Elaboración de la estructura del ADN y ARN en papel.pdfKEVINYOICIAQUINOSORI
 
Una estrategia de seguridad en la nube alineada al NIST
Una estrategia de seguridad en la nube alineada al NISTUna estrategia de seguridad en la nube alineada al NIST
Una estrategia de seguridad en la nube alineada al NISTFundación YOD YOD
 
Seleccion de Fusibles en media tension fusibles
Seleccion de Fusibles en media tension fusiblesSeleccion de Fusibles en media tension fusibles
Seleccion de Fusibles en media tension fusiblesSaulSantiago25
 
TAREA 8 CORREDOR INTEROCEÁNICO DEL PAÍS.pdf
TAREA 8 CORREDOR INTEROCEÁNICO DEL PAÍS.pdfTAREA 8 CORREDOR INTEROCEÁNICO DEL PAÍS.pdf
TAREA 8 CORREDOR INTEROCEÁNICO DEL PAÍS.pdfAntonioGonzalezIzqui
 
Hanns Recabarren Diaz (2024), Implementación de una herramienta de realidad v...
Hanns Recabarren Diaz (2024), Implementación de una herramienta de realidad v...Hanns Recabarren Diaz (2024), Implementación de una herramienta de realidad v...
Hanns Recabarren Diaz (2024), Implementación de una herramienta de realidad v...Francisco Javier Mora Serrano
 
Manual_Identificación_Geoformas_140627.pdf
Manual_Identificación_Geoformas_140627.pdfManual_Identificación_Geoformas_140627.pdf
Manual_Identificación_Geoformas_140627.pdfedsonzav8
 

Último (20)

clases de dinamica ejercicios preuniversitarios.pdf
clases de dinamica ejercicios preuniversitarios.pdfclases de dinamica ejercicios preuniversitarios.pdf
clases de dinamica ejercicios preuniversitarios.pdf
 
2. UPN PPT - SEMANA 02 GESTION DE PROYECTOS MG CHERYL QUEZADA(1).pdf
2. UPN PPT - SEMANA 02 GESTION DE PROYECTOS MG CHERYL QUEZADA(1).pdf2. UPN PPT - SEMANA 02 GESTION DE PROYECTOS MG CHERYL QUEZADA(1).pdf
2. UPN PPT - SEMANA 02 GESTION DE PROYECTOS MG CHERYL QUEZADA(1).pdf
 
SOLICITUD-PARA-LOS-EGRESADOS-UNEFA-2022.
SOLICITUD-PARA-LOS-EGRESADOS-UNEFA-2022.SOLICITUD-PARA-LOS-EGRESADOS-UNEFA-2022.
SOLICITUD-PARA-LOS-EGRESADOS-UNEFA-2022.
 
ECONOMIA APLICADA SEMANA 555555555544.pdf
ECONOMIA APLICADA SEMANA 555555555544.pdfECONOMIA APLICADA SEMANA 555555555544.pdf
ECONOMIA APLICADA SEMANA 555555555544.pdf
 
Linealización de sistemas no lineales.pdf
Linealización de sistemas no lineales.pdfLinealización de sistemas no lineales.pdf
Linealización de sistemas no lineales.pdf
 
Voladura Controlada Sobrexcavación (como se lleva a cabo una voladura)
Voladura Controlada  Sobrexcavación (como se lleva a cabo una voladura)Voladura Controlada  Sobrexcavación (como se lleva a cabo una voladura)
Voladura Controlada Sobrexcavación (como se lleva a cabo una voladura)
 
SSOMA, seguridad y salud ocupacional. SST
SSOMA, seguridad y salud ocupacional. SSTSSOMA, seguridad y salud ocupacional. SST
SSOMA, seguridad y salud ocupacional. SST
 
IPERC Y ATS - SEGURIDAD INDUSTRIAL PARA TODA EMPRESA
IPERC Y ATS - SEGURIDAD INDUSTRIAL PARA TODA EMPRESAIPERC Y ATS - SEGURIDAD INDUSTRIAL PARA TODA EMPRESA
IPERC Y ATS - SEGURIDAD INDUSTRIAL PARA TODA EMPRESA
 
Unidad 3 Administracion de inventarios.pptx
Unidad 3 Administracion de inventarios.pptxUnidad 3 Administracion de inventarios.pptx
Unidad 3 Administracion de inventarios.pptx
 
¿QUE SON LOS AGENTES FISICOS Y QUE CUIDADOS TENER.pptx
¿QUE SON LOS AGENTES FISICOS Y QUE CUIDADOS TENER.pptx¿QUE SON LOS AGENTES FISICOS Y QUE CUIDADOS TENER.pptx
¿QUE SON LOS AGENTES FISICOS Y QUE CUIDADOS TENER.pptx
 
Caldera Recuperadora de químicos en celulosa tipos y funcionamiento
Caldera Recuperadora de químicos en celulosa  tipos y funcionamientoCaldera Recuperadora de químicos en celulosa  tipos y funcionamiento
Caldera Recuperadora de químicos en celulosa tipos y funcionamiento
 
estadisticasII Metodo-de-la-gran-M.pdf
estadisticasII   Metodo-de-la-gran-M.pdfestadisticasII   Metodo-de-la-gran-M.pdf
estadisticasII Metodo-de-la-gran-M.pdf
 
Diapositiva de Topografía Nivelación simple y compuesta
Diapositiva de Topografía Nivelación simple y compuestaDiapositiva de Topografía Nivelación simple y compuesta
Diapositiva de Topografía Nivelación simple y compuesta
 
Reporte de Exportaciones de Fibra de alpaca
Reporte de Exportaciones de Fibra de alpacaReporte de Exportaciones de Fibra de alpaca
Reporte de Exportaciones de Fibra de alpaca
 
Elaboración de la estructura del ADN y ARN en papel.pdf
Elaboración de la estructura del ADN y ARN en papel.pdfElaboración de la estructura del ADN y ARN en papel.pdf
Elaboración de la estructura del ADN y ARN en papel.pdf
 
Una estrategia de seguridad en la nube alineada al NIST
Una estrategia de seguridad en la nube alineada al NISTUna estrategia de seguridad en la nube alineada al NIST
Una estrategia de seguridad en la nube alineada al NIST
 
Seleccion de Fusibles en media tension fusibles
Seleccion de Fusibles en media tension fusiblesSeleccion de Fusibles en media tension fusibles
Seleccion de Fusibles en media tension fusibles
 
TAREA 8 CORREDOR INTEROCEÁNICO DEL PAÍS.pdf
TAREA 8 CORREDOR INTEROCEÁNICO DEL PAÍS.pdfTAREA 8 CORREDOR INTEROCEÁNICO DEL PAÍS.pdf
TAREA 8 CORREDOR INTEROCEÁNICO DEL PAÍS.pdf
 
Hanns Recabarren Diaz (2024), Implementación de una herramienta de realidad v...
Hanns Recabarren Diaz (2024), Implementación de una herramienta de realidad v...Hanns Recabarren Diaz (2024), Implementación de una herramienta de realidad v...
Hanns Recabarren Diaz (2024), Implementación de una herramienta de realidad v...
 
Manual_Identificación_Geoformas_140627.pdf
Manual_Identificación_Geoformas_140627.pdfManual_Identificación_Geoformas_140627.pdf
Manual_Identificación_Geoformas_140627.pdf
 

procesos

  • 1. Practica 2. Creación de procesos e hilos 1. Objetivos 1).-Que el alumno aprenda a crear procesos y a controlar la estructura jerár- quica resultante con las llamadas al sistema fork, getpid, getppid, wait y exit. 2).-Que el alumno aprenda a gestionar hilos con la biblioteca de funciones pthread (POSIX Threads). 2. Introducción 2.1. Creación de proceso con fork. Un proceso es cualquier programa o comando en ejecución con un identifica- dor de proceso o pid asignado por el sistema y que está en alguno de los siguientes estados: Running (R), Sleeping (S), Waiting (D), Stopped (T) o Zombie (Z). To- dos los procesos, exepto el proceso init cuyo pid es 1, tienen un proceso creador al cual llamamos su proceso padre. Una llamada al sistema para crear procesos en Linux es fork() y su declaración es: #include <unistd.h> #include <sys/types.h> pid_t fork(void); Después de la invocación de fork() se crea un proceso hijo con el mismo código que el proceso padre y una copia de sus datos (variables y valores). El proceso padre recibe como valor de retorno un entero positivo que corresponde al pid de su hijo y el proceso hijo recibe como valor de retorno 0, este valor se pude utilizar para controlar las instrucciones que debe ejecutar cada proceso. Por otro lado, fork() regresa -1 si el proceso hijo no se puede crear. Ambos procesos continúa con la ejecución del programa a partir del fork() de manera concurrente. Ambos procesos comparten los archivos abiertos pero cada uno tiene 1
  • 2. su propio contador de programa. Adicionalmente, las funciones getpid() y getppid() regresan el pid y el ppid (pid del proceso padre) de quien las invoca, su declaración es: #include <unistd.h> pid_t getpid(void); pid_t getppid(void); Ejemplo 1. /* * $ gcc 1fork.c -o fork * $ ./fork * * Después de invocar fork(): El proceso hijo incrementa en uno *sus variables y escribe el resultado en el archivo salida.txt, el proceso *padre incrementa en dos sus variables y escribe el resultado en el archivo *salida.txt, ambos procesos imprimen el contenido del archivo. * *Cada proceso maneja sus variables de forma independiente aun siendo globales. *Los dos procesos tienen acceso concurrente al archivo, cada proceso cierra el archivo para sí mismo. * */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> int x=1; //variable global int main() { pid_t ret; FILE *apArch; int y=2; //variable local if( (apArch=fopen("salida.txt","w")) == NULL ){ printf("Error al abrir archivon"); exit(0); } ret=fork(); switch(ret){ case -1:printf("No se pude crear un proceso hijo.n"); break; case 0: x=x+1; y=y+1; fprintf(apArch,"soy el proceso hijo pid: %d, pidPadre: %d, x= %d,y = %dn",getpid(),getppid(),x,y); fclose(apArch); break; default:x=x+2; y=y+2; 2
  • 3. fprintf(apArch,"soy el proceso padre pid: %d, pidHijo: %d, x= %d,y = %dn",getpid(),ret,x,y); fclose(apArch); } system("cat ./salida.txt"); //Muestra el contenido del archivo //lo hacen los dos procesos. return 1; } Compilación y ejecución $ gcc 1fork.c -o fork $ ./fork soy el proceso padre pid:17275, pidHijo: 17276, x=3,y=4 soy el proceso hijo pid:17276, pidPadre: 17275, x=2,y=3 soy el proceso padre pid:17275, pidHijo: 17276, x=3,y=4 soy el proceso hijo pid:17276, pidPadre: 17275, x=2,y=3 2.2. Comunicación mediante wait y exit. Después de una invocación a fork() el proceso padre puede esperar la ter- minación de su hijo con la función wait() y su hijo puede avisarle a su padre que ya terminó con la función exit(), su declaración es: #include <sys/types.h> #include <sys/wait.h> #include <unistd.h> pid_t wait(int *status); void exit(int st); exit() termina el proceso que la invoca y le regresa el valor de st al sistema quien lo almacena en status. wait() bloquea la ejecución del proceso padre hasta que alguno de sus procesos hijos invoca exit(). wait() regresa el pid del proceso que invocó exit() y continúa ejecutándose, dos de las macros que se pueden utilizar para evaluar el contenido de status son: WIFEXITED(status) Distinto de cero si el hijo terminó normalmente. WEXITSTATUS(status) Evalúa los ocho bits menos significativos del código de retorno del hijo, puede ser el argumento de exit() o de return(), es decir st. 3
  • 4. Ejemplo 2 y 3 Descargar el .zip de moodle. Compilación y ejecución $ gcc 2fork.c -o fork $ ./fork $ ps -eo pid,user,comm|grep fork|head -n 1|awk ’{print $1}’|xargs pstree -cp $ gcc 3fork.c -o fork $ ./fork $ ps -eo pid,user,comm|grep fork|head -n 1|awk ’{print $1}’|xargs pstree -cp 2.3. Hilos POSIX POSIX Threads (Portable Operating System Interface Threads) es una biblio- teca de funciones proporcionada por los sistemas operativos tipo UNIX para la gestión de hilos. Para trabajar con hilos POSIX es necesario incluir la biblioteca de funciones pthread.h en el encabezado de los programas en lenguaje C y compilar con la opción lpthread. Algunas de sus funciones son: #include <pthread.h> int pthread_create(pthread_t *tid, const pthread_attr_t *attr, (void *)(*star_routine)(void *), void *arg); void pthread_exit(void *value_ptr); int pthread_join(pthread_t thread, void **value_ptr); La función pthread_create sirve para crear hilos, regresa 0 si tuvo éxito y un valor de error en caso contrario, sus argumentos deben ser: tid Un apuntador a la variable donde se almacenará el identificador del hilo, si es que la llamada tuvo éxito. attr Es un apuntador a la variable donde se almacenan los atributos que el sistema debe asignar al hilo. Si es igual a NULL, tendrá los atributos por omisión. (*star_routine) Es una referencia a la función que el hilo ejecuta cuando es creado. La función devuelve un apuntador sin tipo (void *) y su único argumento es un apuntador sin tipo (void *). Para poder utilizar un argumento de otro tipo se debe hacer un cast al recuperar el valor. 4
  • 5. arg Es el argumento que se le pasa a la función star_routine(). La función pthread_exit termina el hilo que la invoca. El valor del argu- mento value_ptr queda disponible para pthread_join si la primera tuvo éxito. value_ptr debe apuntar a datos que existan después de que el hilo ter- mine. La función pthread_join suspende la ejecución del hilo que la invoca has- ta que el hilo identificado con thread termine, ya sea porque llamó a pthread_exit o por que fue cancelado. Si value_ptr no es NULL, entonces el valor retornado por thread es almacenado en la ubicación apuntado por value_ptr. Ejemplo 4. El hilo principal crea dos hilos y espera a que termine su ejecución, cada uno ejecuta la función ejecutaHilo() con la cual imprime un mensaje y termina, cada hilo se ejecuta a su propia velocidad. Las variables h1 y h2 son referencias a los hilos, asignadas por posix. #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <pthread.h> void ejecutaHilo(); void main() { pthread_t h1,h2; pthread_create(&h1,NULL,(void *)&ejecutaHilo,NULL); pthread_create(&h2,NULL,(void *)&ejecutaHilo,NULL); pthread_join(h1,NULL); pthread_join(h2,NULL); } void ejecutaHilo() { printf("Hilo en ejecución...n"); sleep(5); pthread_exit(NULL); } Compilación y ejecución $ gcc ejemplo1.c -lpthread $ ./a.out Hilo en ejecución... Hilo en ejecución... 5
  • 6. Mientras se está ejecutando, hacer lo siguiente en otra terminal: $ ps -eo pid,user,comm|grep a.out|head -n 1|awk ’{print $1}’|xargs pstree -cp a.out(4411)-----{a.out}(4412) |--{a.out}(4413) Ejemplo 5. La biblioteca de funciones pthread.h le asigna a cada hilo un identificador que se guarda en tid, y se puede obtener con la función pthread_self(). Por otro lado Linux también le asigna un identificador a cada hilo, el cual se puede obtener con la llamada al sistema SYS_gettid que no pertenece a C. Además los hilos pueden ser nombrados por los argumentos de la función que ejecutan. Lo anterior se muestra en el siguiente código.El hilo principal crea dos hilos, cada uno ejecuta la función ejecutaHilo() que recibe un id asignado por el programa, el hilo imprime dicho identificador junto con los identificadores asig- nados por posix y por Linux. #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <pthread.h> #include <syscall.h> void ejecutaHilo(void *id); void main() { pthread_t h1,h2; int id1=10, id2=20; pthread_create(&h1,NULL,(void *)&ejecutaHilo,(void *)&id1); printf("hilo1( %u) creadon",(unsigned int)h1); pthread_create(&h2,NULL,(void *)&ejecutaHilo,(void *)&id2); printf("hilo2( %u) creadon",(unsigned int)h2); pthread_join(h1,NULL); pthread_join(h2,NULL); } void ejecutaHilo(void *id) { int *idh=(int *)(id); int tid=syscall(SYS_gettid);//LLamada al sistema explícita, para obtener el id de Linux printf("Hilo en ejecución con idPosix= %u, idLinux= %d, idPrograma= %dn",(int) pthread_self(),tid,*idh); sleep(7); pthread_exit(NULL); } 6
  • 7. Compilación y ejecución $ gcc ejemplo2.c -o -lpthread $ ./a.out hilo1(2075494144) creado Hilo en ejecución con idPosix=2075494144, idLinux=4262, idPrograma=10 hilo2(2067101440) creado Hilo en ejecución con idPosix=2067101440, idLinux=4263, idPrograma=20 Mientras se está ejecutando, hacer lo siguiente en otra terminal: $ ps -eo pid,user,comm|grep a.out|head -n 1|awk ’{print $1}’|xargs pstree -cp a.out(4411)-----{a.out}(4412) |--{a.out}(4413) Ejemplo 6. Notar el uso de pthread_join y pthread_exit. Notar que se pude hacer referencia al id asignado por posix con h1 y h2, sin necesidad de utilizar pthread_self() Es decir, que los hilos se pueden gestionar con el id asignado por posix (h1 y h2), sin necesidad de conocer el id asignado por Linux. Notar que comparten memoria: Pueden leer las variables globales y las re- ferencias a memoria (apuntadores) son sobre un espacio de memoria com- partido. #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <pthread.h> int varGlobal = 1000; //compartida por los hilos. void ejecutaHilo(void *id); //ejecutada por los hilos. void main() { pthread_t h1,h2; //id posix para los hilos int v1=5, v2=6; //argumentos para la función que ejecutan los hilos int *r1=NULL; //para guardar el valor de exit y leerlo con join int i; pthread_create(&h1,NULL,(void *)&ejecutaHilo,(void *)&v1); pthread_create(&h2,NULL,(void *)&ejecutaHilo,(void *)&v2); for(i=0;i<10;i++){ printf("Hilo principal, varGlobal= %dn",varGlobal+=1); sleep(1); } 7
  • 8. pthread_join(h1,(void **)&r1); printf("hilo1 termina con: %dn",*r1); pthread_join(h2,(void **)&r1); printf("hilo2 termina con: %dn",*r1); } void ejecutaHilo(void *v) { int *vh=(int *)(v); sleep(*vh); //utiliza el argumento recibido. printf("Hilo que recibe %d, espera %ds, imprime varGlobal= %d, modifca val recibidon",*vh,*vh,varGlobal); *vh=5*(*vh); //modifica el argumento recibido. pthread_exit(vh); //termina y deja vh para el join. } Compilación y ejecución $ gcc ejemplo3.c -lpthread $ ./a.out Hilo principal, varGlobal=1001 Hilo principal, varGlobal=1002 Hilo principal, varGlobal=1003 Hilo principal, varGlobal=1004 Hilo principal, varGlobal=1005 Hilo que recibe 5, espera 5s, imprime varGlobal=1005, modifca val recibido Hilo principal, varGlobal=1006 Hilo que recibe 6, espera 6s, imprime varGlobal=1006, modifca val recibido Hilo principal, varGlobal=1007 Hilo principal, varGlobal=1008 Hilo principal, varGlobal=1009 Hilo principal, varGlobal=1010 hilo1 termina con: 25 hilo2 termina con: 30 Mientras se está ejecutando, hacer lo siguiente en otra terminal: $ ps -eo pid,user,comm|grep ej1hilos|head -n 1|awk ’{print $1}’|xargs pstree -cp a.out(4736)-----{a.out}(4737) |--{a.out}(4738) 8
  • 9. 3. Actividades. 1. Construir un árbol binario de procesos de altura N. Hacer que N sea gene- rado aleatoriamente y que el nodo raíz imprima el número total de hijos. Utilizar sleep() para poder visualizar el árbol con el comando visto en los ejercicios. NOTA. No utilizar recursividad. 2. Modificar el ejemplo cuatro para que cada hilo genere dos hilos más y es- pere su finalización. Explicar qué es lo que pasa ¿Quién es el padre de los nuevos hilos? Mostrar el árbol de procesos (hilos). 3. Modificar el ejemplo uno para que un hilo clone al proceso con fork(). Ex- plicar qué es lo que pasa ¿También se clonan los hilos? Mostrar el árbol de procesos (hilos). 4. Después de haber ejecutado el fork() del punto anterior. Dado que todos los hilos comparten los recursos del proceso al que pertenecen ¿Es posible que un hilo sepa a qué proceso pertenece? En caso afirmativo ¿Cómo? 5. Modificar el ejemplo tres para que genere N hilos y los guarde en un arreglo. Cada hilo debe ejecutar la función ejecutaHilo recibiendo como argu- mento la localidad (i) donde se encuentra el hilo, el hilo debe escribir su va- lor i en la variable global y salir con pthread_exit(). El hilo principal debe esperar por cada uno de los hilos con la función pthread_join(). N debe ser definido en el programa o dado por el usuario. Asegurarse de que los hilos se ejecuten concurrentemente, es decir, no serializar la ejecución con sleep u otro código. 6. ¿Cuál es el valor que se espera que tenga la variable global? y ¿Por qué? 7. Hacer que cada hilo del programa anterior, además de su identificador (i), imprima quien es su vecino posterior (i+1) y anterior (i-1), suponiendo que el arreglo es circular. Notar que no es necesaria la comunicación entre hilos, cada hilo debe calcular i-1 e i+1 a partir de i. 9