Portada Paralelismo Curso de programación en C moderno Procesos (II Edición) fork() Ejemplo Zombies Señales Ejemplo Neira Ayuso, Pablo Falgueras García, Carlos Tema 16 Fork Índice Portada Paralelismo 1 Paralelismo Procesos fork() Ejemplo Zombies Señales Ejemplo 2 Procesos 3 fork() Ejemplo Zombies 4 Señales Ejemplo Paralelismo Portada Paralelismo Procesos fork() Ejemplo Zombies Señales Ejemplo • A veces es necesario que nuestro programa realice varias tareas a la vez • Otras veces es interesante dividir el trabajo en partes independientes que pueden realizarse simultáneamente (en paralelo). Esto puede mejorar enormemente la eficiencia de nuestro programa, incluso si nuestro hardware no tiene la capacidad de ejecutar varios procesos a la vez • No siempre es lo mejor. Paralelizar un programa tiene un coste de rendimiento que, a veces, puede superar a la mejora obtenida. Procesos Portada Paralelismo Procesos fork() Ejemplo Zombies Señales Ejemplo • En Unix, hilos y procesos son esencialmente lo mismo • Todo proceso tiene asociado un número que lo identifica: PID(Process IDentification) • En Unix todos procesos se crean mediante la llamada al sistema pid_t fork(void); fork() Portada • En el momento en que un programa llama a fork(), se Paralelismo duplica. Procesos • A partir de entonces existirán dos procesos (padre e hijo) fork() con el mismo código, las mismas variables, etc. Ejemplo Zombies • El proceso hijo tendrá una copia de la memoria del padre Señales Ejemplo en el instante en el que se llamó a fork(). • La memoria es independiente. Si uno de los procesos modifica una variable, no afecta a la variable del otro proceso. (Existe la opción de que ambos procesos compartan la memoria, pero se excede del propósito de este curso) Ejemplo Portada Paralelismo Procesos fork() Ejemplo Zombies Señales Ejemplo 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 #i n c l u d e #i n c l u d e #i n c l u d e #i n c l u d e < s t d i o . h> < s t d l i b . h> < u n i s t d . h> <s y s / w a i t . h> i n t main ( ) { int pid ; i n t var = 0; pid = fork () ; i f ( p i d == −1) { perror (" fork ") ; e x i t ( EXIT_FAILURE ) ; } i f ( p i d == 0 ) { p r i n t f ( " Soy e l h i j o \ n \ tPID = %d \ n " , getpid () ) ; var = 10; p r i n t f ( " v a r d e l h i j o = %d \ n " , v a r ) ; } else { p r i n t f ( " Soy e l p a d r e \ n \ tPID = %d \ n \ tPID pid ) ; 24 25 w a i t ( NULL ) ; // E s p e r a m o s a que t e r m i n e 26 p r i n t f ( " v a r d e l p a d r e = %d \ n " , v a r ) ; 27 } 28 29 r e t u r n EXIT_SUCCESS ; 30 } h i j o = %d \ n " , el hijo getpid () , Ejemplo Portada Paralelismo Procesos fork() Ejemplo Zombies Señales Ejemplo Soy el hijo PID = 7590 Soy el padre PID = 7589 PID hijo = 7590 var del padre = 0 var del hijo = 10 Zombies Portada Paralelismo Procesos fork() Ejemplo Zombies Señales Ejemplo • Cuando un proceso hijo muere, no muere del todo. Permanece en un estado llamado zombie que permite al padre recuperar información de él aun cuando ha terminado (el código de error por ejemplo) • El sistema puede llegar a colapsarse si se crean mucho procesos zombies. Conclusión: Siempre llamar a wait()) • Si un proceso padre muere antes que su hijo (no ha llamado a (wait()), el comportamiento depende del SO: • El padre del proceso hijo pasa a ser el proceso init (PID = 1) • El hijo es matado también inmediatamente Señales Portada Paralelismo Procesos • Son un medio para que los procesos puedan interaccionar fork() Ejemplo Zombies entre sí. Un proceso envía una señal y el otro la recibe. Señales • Existen muchos tipos de señales distintas (man 7 signal) Ejemplo • Para reaccionar ante la recepción de una señal debemos instalar un callback Ejemplo Portada Paralelismo Procesos fork() Ejemplo Zombies Señales Ejemplo 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 #i n c l u d e #i n c l u d e #i n c l u d e #i n c l u d e < s t d i o . h> < s t d l i b . h> < u n i s t d . h> <s y s / s i g n a l . h> void sigint_hdl ( int sig ) { s t a t i c i n t cnt = 0; i f ( cnt < 2) { p r i n t f ( "No q u i e r o m o r i r ! ! \ n " ) ; c n t ++; } else{ p r i n t f ( " V a a a l e e e , me muero \ n " ) ; e x i t ( EXIT_SUCCESS ) ; } } i n t main ( ) { s t r u c t s i g a c t i o n sa ; sa . sa_handler = s i g i n t _ h d l ; s i g e m p t y s e t (& s a . sa_mask ) ; if ( s i g a c t i o n ( SIGINT , &sa , NULL ) == −1) { perror (" sigaction ") ; r e t u r n EXIT_FAILURE ; } w h i l e ( 1 ) ; // No q u i e r o r e t u r n EXIT_SUCCESS ; } morir