Documentos de Académico
Documentos de Profesional
Documentos de Cultura
PRCTICAS DE SS.OO.
I.I./I.T.I. Sistemas/I.T.I. Gestin
Enero de
ndice
1. La llamada
1.1. Ejemplo de uso de fork . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.2. Ejemplo de uso de exec . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.3. Ejemplo de uso de fork y exec conjuntamente . . . . . . . . . . . . . . . . . . . . . 2.1. fork_exec_wait.c 2.2. runcom.c . . . . . 2.3. signal.c . . . . . 2.4. sigaction.c . . . . 2.5. sigaction_chld.c 2.6. envia.c . . . . . . 2.7. alarma.c . . . . . 2.8. pipe3men.c . . . 2.9. pipecapa.c . . . . 2.10. pipe2com.c . . . 2.11. fo_esc.c . . . . 2.12. fo_lee.c . . . .
PROCESOS COMUNICACIONES ENTRE PROCESOS. SEALES COMUNICACIONES ENTRE PROCESOS. TUBERAS COMUNICACIONES ENTRE PROCESOS. FIFO's BIBLIOGRAFA Listados
fork
3 4 5
2.
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
6 7 8 9 10 12 13 15 16 17 19 21
22 23 24 25 25
3. 4. 5. 6. 7.
1.
La llamada
fork
2.
Listados
2.1. fork_exec_wait.c
1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 41 43
#include <s t d i o . h> #include < s t d l i b . h> #include <u n i s t d . h> int main ( void ) { int p i d ;
p r i n t f ( " Hasta a q u hay un n i c o p r o c e s o . . . \ n" ) ; p r i n t f ( " Primera llamada a f o r k . . . \ n" ) ;
if
else if if
Hola , yo soy e l p r i m e r h i j o . . . \ n" ) ; Voy a pararme d u r a n t e 60 s e g . y l u e g o t e r m i n a r . . . \ n" ) ; { Hola , soy e l padre . El p i d de mi h i j o e s : % d\n" , p i d ) ;
/ Creamos un nuevo p r o c e s o . / pid = f o r k ( ) ; ( p i d == 0 ) { p r i n t f ( "HIJO2 : Hola , soy e l segundo h i j o . . . \ n" ) ; p r i n t f ( "HIJO2 : El segundo h i j o va a e j e c u t a r l a orden ' l s ' . . . \ n" ) ; e x e c l p ( " l s " , " l s " ,NULL) ; p r i n t f ( "HIJO2 : S i ve e s t e mensaje , e l e x e c l p no f u n c i o n . . . \ n" ) ; } ( pid > 0) { p r i n t f ( "PADRE: Hola o t r a vez . Pid de mi segundo h i j o : % d\n" , p i d ) ; p r i n t f ( "PADRE: Voy a e s p e r a r a que t e r m i n e n mis h i j o s . . . \ n" ) ; p r i n t f ( "PADRE: Ha terminado mi h i j o % d\n" , w a i t (NULL) ) ; p r i n t f ( "PADRE: Ha terminado mi h i j o % d\n" , w a i t (NULL) ) ; }
else if else
2.2. runcom.c
2 4 6 8 10 12 14 16 18 20
#include
" s m a l l s h . h"
/ E j e c u t a una orden . " c l i n e " e s una a r r a y de p a l a b r a s que c o n t i e n e e l nombre de l a orden y l o s parmetros de d i c h a orden . " where " i n d i c a s i d i c h a orden s e debe e j e c u t a r en primer o segundo p l a n o . /
runcommand (
int
char c l i n e , int where ) int pid , e x i t s t a t , r e t ; if ( ( p i d = f o r k ( ) ) < 0 ) { perror (" smallsh ") ; return ( 1) ; if
( p i d == 0 ) { execvp ( c l i n e , c l i n e ) ; perror ( c l i n e ) ;
22 24 26 28 30 32 34 36 38 40
exit (127) ;
h i j o . / orden . / s i no s e ha p o d i d o t a n t o , s e ha
/ Estamos en e l padre . S i l a orden s e e j e c u t a en segundo plano , no debemos e s p e r a r por l o que mostramos e l p i d d e l nuevo p r o c e s o y regresamos . / ( where == BACKGROUND) { p r i n t f ( " [ I d e n t i f i c a d o r de p r o c e s o : % ] \ n" , p i d ) ; d (0) ; }
if
return
while
}
return ( r e t
2.3. signal.c
1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39
El s i g u i e n t e programa muestra cmo t r a b a j a n l a s s e a l e s . E s t e programa c a p t u r a l a s e a l SIGINT ( s e a l de i n t e r r u p c i n generada con CTRL C) . Probar e l programa r e p e t i d a s v e c e s . En una de e l l a s , no p u l s a r CTRL C, en o t r a p u l s a r "una v e z " CTRL C a n t e s de que t e r m i n e l a e j e c u c i n y o t r a p u l s a r "ms de una v e z " CTRL C a n t e s de que t e r m i n e l a e j e c u c i n . /
#include <s i g n a l . h> #include <s t d i o . h> void t r a t a _ s i g ( int ) ; int main ( void ) {
/ E s t e e s e l p r o t o t i p o de l a f u n c i n que va a t r a t a r l a s e a l . /
return
void
}
int
2.4. sigaction.c
2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42 44 46 48 50 52
El s i g u i e n t e programa muestra e l uso de l a f u n c i n s i g a c t i o n . E s t e programa c a p t u r a l a s e a l SIGINT ( s e a l de i n t e r r u p c i n generada con CTRL C) una v e z . Probar e l programa r e p e t i d a s v e c e s . En una de e l l a s , no p u l s a r CTRL C, en o t r a p u l s a r "una v e z " CTRL C a n t e s de que t e r m i n e l a e j e c u c i n y o t r a p u l s a r "ms de una v e z " CTRL C a n t e s de que t e r m i n e l a e j e c u c i n . /
#include <s i g n a l . h> #include <s t d i o . h> #include < s t d l i b . h> void t r a t a _ s i g ( int ) ; int main ( void ) { struct s i g a c t i o n a c c i o n ;
sigset_t conjunto ;
/ E s t e e s e l p r o t o t i p o de l a f u n c i n que va a t r a t a r l a s e a l . /
/ E s t a b l e c e m o s e l comportamiento d e l programa a n t e l a s e a l SIGINT . La f u n c i n s i g e m p t y s e t p e r m i t e c o n s t r u i r un con j u n t o de s e a l e s a b l o q u e a r . No vamos a b l o q u e a r ninguna . / s i g e m p t y s e t (& c o n j u n t o ) ; a c c i o n . sa_handler=t r a t a _ s i g ; a c c i o n . sa_mask=c o n j u n t o ; a c c i o n . s a _ f l a g s=SA_ONESHOT; a c c i o n . s a _ r e s t o r e r=NULL; / Hasta que no s e e j e c u t e l a s i g u i e n t e orden , l a s e a l SIGINT p r o v o c a r l a t e r m i n a c i n d e l p r o c e s o ( a c c i n por d e f e c t o ) . /
s i g a c t i o n ( SIGINT,& a c c i o n ,NULL) ;
return
void
}
int
2.5. sigaction_chld.c
2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42 44 46 48 50 52 54
El s i g u i e n t e programa muestra e l uso de l a f u n c i n s i g a c t i o n con l a s e a l SIGCHLD. La r u t i n a de t r a t a m i e n t o o b t i e n e un parmetro a d i c i o n a l l l a m a d o " i n f o " con i n f o r m a c i n a d i c i o n a l , e n t r e o t r a s , e l PID d e l programa que acaba de t e r m i n a r y que h i z o que s e l a n z a r a l a s e a l SIGCHLD. El h i j o termina t r a s imprimir un mensaje , y e l padre r e c i b e l a s e a l en cuanto e s t e termina . / <s i g n a l . h> <s t d i o . h> < s t d l i b . h>
void
/ E s t a b l e c e m o s e l comportamiento d e l programa a n t e l a s e a l SIGCHLD. La f u n c i n s i g e m p t y s e t p e r m i t e c o n s t r u i r un con j u n t o de s e a l e s a b l o q u e a r m i e n t r a s s e t r a t a SIGCHLD. / s i g e m p t y s e t (& c o n j u n t o ) ; s i g a d d s e t (& c on ju nt o , SIGCHLD) ; a c c i o n . s a _ s i g a c t i o n=t r a t a m i e n t o ; a c c i o n . sa_mask=c o n j u n t o ; a c c i o n . s a _ f l a g s=SA_RESTART | SA_SIGINFO ; a c c i o n . s a _ r e s t o r e r=NULL; / A c t i v a e l t r a t a m i e n t o de SIGCHLD / s i g a c t i o n (SIGCHLD,& a c c i o n , ( )NULL) ;
void
if
return else if
( p i d == 0 ) { p r i n t f ( "HIJO : Hola , yo soy e l p r i m e r h i j o . . . \ n" ) ; p r i n t f ( "HIJO : Tras 5 s e g u n d o s voy a t e r m i n a r para que " " e l padre r e c i b a mi s e a l . \ n" ) ; sleep (5) ; 0; ( pid > 0) { p r i n t f ( "PADRE: Hola , soy e l padre . El p i d de mi h i j o e s : % d\n" , p i d ) ; p r i n t f ( "PADRE: R e a l i z a n d o c u a l q u i e r o t r a o p e r a c i n . . . \ n" ) ; sleep (10) ;
return
10
}
56 58 60 62 64 66 68 70 72 74
} {
return
void nada )
/ Acceso a i n f o >si_pid , i n f o >s i _ s i g n o , e t c . / / ( s i _ p i d e s e l p i d d e l p r o c e s o que e n v a l a s e a l / p r i n t f ( "PADRE: El h i j o que ha terminado t i e n e e l p i d % d\n" , i n f o >s i _ p i d ) ; / Esperar a l p r o c e s o h i j o ( o b l i g a t o r i o para que no quede Zombie ) / w a i t (& e x i t s t a t ) ;
} p r i n t f ( "PADRE: El h i j o r e t o r n % . \ n" , e x i t s t a t ) ; d
11
2.6. envia.c
2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42 44 46 48 50
#include <s i g n a l . h> #include <s t d i o . h> int n t i m e s =0; int main ( int argc , char argv [ ] ) { int pid , ppid ; void p_action ( int ) , c _ a c t i o n ( int ) ;
/ E s t a b l e c e m o s l a a c c i o n de l a s e a l SIGUSR1 para e l padre . / s i g n a l ( SIGUSR1 , p_action ) ;
/ Error . / / H i j o . /
/ E s t a b l e c e m o s l a a c c i n para e l h i j o . / s i g n a l ( SIGUSR1 , c _ a c t i o n ) ; / Obtenemos e l p i d d e l padre . / ppid=g e t p p i d ( ) ; (;;) { sleep (1) ; k i l l ( ppid , SIGUSR1 ) ; pause ( ) ; } : / Padre . / (;;) { pause ( ) ; sleep (1) ; k i l l ( pid , SIGUSR1 ) ; }
for
default for
} }
return
0;
void
int
void
int
12
2.7. alarma.c
2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42 44 46 48 50 52 54
/ El s i g u i e n t e programa me p e r m i t e e s t a b l e c e r una alarma para que imprima un mensaje cuando t r a n s c u r r a n l o s minutos que s e l e dan como parmetro . /
#include <s t d i o . h> #include <s i g n a l . h> #include < s t d l i b . h> #define TRUE 1 #define FALSE 0 #define BELLS " \007\007\007 " int a l a r m _ f l a g = FALSE ;
/ E s t e p r o c e d i m i e n t o maneja l a s e a l SIGALRM. / setflag ( nada ) { a l a r m _ f l a g = TRUE; }
void int
int
argv [ ] ) {
if
}
/ Aqu creamos un p r o c e s o en segundo p l a n o . / = fork () ) { / Error . / p e r r o r ( argv [ 0 ] ) ; exit (1) ; 0: / H i j o . Es e l p r o c e s o que s e queda en segundo p l a n o . / ; : / Padre . Muestra p i d d e l p r o c e s o h i j o y termina . / p r i n t f ( " % > I d e n t i f i c a d o r de p r o c e s o : % s d\n" , argv [ 0 ] , p i d ) ; 0; }
/ Fijamos l a a c c i n para l a alarma . / s i g n a l (SIGALRM, s e t f l a g ) ; / Activamos l a alarma . / alarm ( n s e c s ) ; / Esperamos h a s t a que r e c i b a m o s una s e a l . . . / pause ( ) ;
13
56 58 60 62 64 66
/ S i l a s e a l r e c i b i d a e s SIGALRM, mostramos e l mensaje . / ( a l a r m _ f l a g == TRUE) { p r i n t f (BELLS) ; p u t c h a r ( ' \n ' ) ; ( j = 2 ; j < a r g c ; j ++) p r i n t f ( " % " , argv [ j ] ) ; s p r i n t f ( " \n" ) ; }
if
for
return
0;
14
2.8. pipe3men.c
2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42 44 46 48 50 52
El s i g u i e n t e programa muestra e l uso de t u b e r a s para p a s a r i n f o r m a c i n de un p r o c e s o a uno de s u s d e s c e n d i e n t e s o v i c e v e r s a . En n u e s t r o ejemplo , un padre e n v a t r e s mensajes a un h i j o que s e encarga de l e e r l o s . /
/ Tamao d e l mensaje . /
no 1 " ; no 2 " ; no 3 " ;
char msg1 = " Hola , mundo char msg2 = " Hola , mundo char msg3 = " Hola , mundo int main ( void ) { char i n b u f [ MSGSIZE ] ; int p [ 2 ] , j , p i d ; if return
/ Mensajes a e n v i a r . /
/ Abrimos l a t u b e r a . / ( pipe (p) < 0) { p e r r o r ( " llamada a p i p e " ) ; 1; } / Creamos e l p r o c e s o h i j o . Dicho p r o c e s o h e r e d a l o s d e s c r i p t o r e s de l o s dos e x tr e mo s de l a t u b e r a . / ( ( pid = f o r k ( ) ) < 0) { p e r r o r ( " llamada a l f o r k " ) ; 2; }
if
return
/ S i e s e l padre , e n t o n c e s c i e r r a e l d e s c r i p t o r d e l f i c h e r o de l e c t u r a y e s c r i b e en l a t u b e r a l o s t r e s mensajes . / ( pid > 0) { close (p [ 0 ] ) ; w r i t e ( p [ 1 ] , msg1 , MSGSIZE) ; w r i t e ( p [ 1 ] , msg2 , MSGSIZE) ; w r i t e ( p [ 1 ] , msg3 , MSGSIZE) ; w a i t (NULL) ; }
if
if
for
return
15
2.9. pipecapa.c
2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42
#include <s i g n a l . h> #include <s t d i o . h> #include < s t d l i b . h> int count ; void alrm_action ( int ) ; int main ( void ) { int p [ 2 ] ; char c= ' x ' ; if ( p i p e ( p ) <0) { for
/ Desactivamos l a alarma . S i no l l e g a m o s aqu , e s por que l a orden w r i t e a n t e r i o r s e ha quedado b l o q u e a d a a l e s t a r l l e n a l a t u b e r a . Al no d e s a c t i v a r l a alarma , s e d i s p a r a y s e e j e c u t a e l p r o c e d i m i e n t o " alrm_action " que muestra un mensaje y termina l a e j e c u c i n d e l p r o c e s o . / alarm ( 0 ) ;
if
} }
return
/ Se e j e c u t a cuando s e r e c i b e l a s e a l SIGALRM. / alrm_action ( nada ) { p r i n t f ( " E s c r i t u r a bloqueada d e s p u s de % c a r a c t e r e s \n" , count ) ; d exit (0) ; }
void
int
16
2.10. pipe2com.c
1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 41 43 45 47 49 51 53
El s i g u i e n t e programa muestra e l uso de l a s t u b e r a s y l a l l a m a d a a l s i s t e m a " e x e c " . En c o n c r e t o , s e ve cmo s e puede c o n e c t a r l a s a l i d a e s t n d a r de un programa a l a e n t r a d a e s t n d a r de o t r o ( e s t e meca nismo s e c o n s i g u e en e l s h e l l con e l s m b o l o ' | ' ) . /
/ Une dos r d e n e s mediante una t u b e r a . Como parmetros r e c i b e dos a r r a y s de cadenas , cada uno con e l nombre de l a orden y parmetros c o r r e s p o n d i e n t e s . / join ( com1 [ ] , com2 [ ] ) {
int
int
char
char
p [2] , status ;
switch ( f o r k ( ) ) { case 1: / Error . / f a t a l ( " Primera llamada a f o r k en j o i n " ) ; case 0 : / H i j o . / break ; default : / Padre . Espera a que su h i j o t e r m i n e w a i t (& s t a t u s ) ; return ( s t a t u s ) ;
/ E s t e e s e l c d i g o d e l primer h i j o c r e a d o . / / Creamos l a t u b e r a . / ( pipe (p) < 0) f a t a l ( " Llamada a p i p e en j o i n " ) ;
/ Creamos un p r o c e s o h i j o para e j e c u t a r l a s r d e n e s . /
y r e g r e s a . /
if
/ / /
/ S i s e r e g r e s a de " e x e c v p " e s porque ha f a l l a d o . / execvp ( com1 [ 0 ] , com1 ) ; f a t a l ( " Primera llamada a execvp en j o i n " ) ;
default :
/ Cdigo d e l primer h i j o . /
17
55 57 59 61 63 65 67 69 71 73 75 77 79 81 83
/ / /
/ S i s e r e g r e s a de " e x e c v p " e s porque ha f a l l a d o . / execvp ( com2 [ 0 ] , com2 ) ; f a t a l ( " Segunda llamada a execvp en j o i n " ) ;
/ Primera orden y s u s parmetros . / one [ ] = { " l s " , " l " , " / u s r / l i b " ,NULL };
int
main ( ret ;
void )
return
18
2.11. fo_esc.c
2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42 44 46 48 50 52 54
El s i g u i e n t e programa muestra e l uso de una "FIFO " . E s t e programa e s c r i b e en l a FIFO l o s mensajes que r e c i b e como parmetros . Antes de e j e c u t a r e s t e programa debemos c r e a r l a FIFO ( con " m k f i f o t u b o ") y e j e c u t a r en segundo p l a n o e l programa que l e e l o s mensajes de l a FIFO (" pag160 &") .
#include < f c n t l . h> #include <s t d i o . h> #include <e r r n o . h> #include < s t d l i b . h> #include <s t r i n g . h> #define MSGSIZ 63 / extern int e r r n o ; char f i f o = " tubo " ; void
} fatal ( perror ( s ) ; exit (1) ; main (
char
s ) {
int
int
argc ,
char
argv [ ] ) {
/ Abrimos l a FIFO para s l o e s c r i t u r a y con e s c r i t u r a s no b l o q u e a n t e s cuando l a FIFO e s t l l e n a (O_NDELAY) . / ( ( f d = open ( f i f o , O_WRONLY | O_NDELAY) ) < 0 ) f a t a l ( " f a l l l a a p e r t u r a de l a FIFO" ) ;
if
for
s t r c p y ( msgbuf , argv [ j ] ) ;
19
56 58 60 62 64 66 68
} }
if
return
0;
Nota . El s i g n i f i c a d o de EAGAIN e s : " Recurso temporalmente no d i s p o n i b l e , i n t e n t a r o t r a v e z ms t a r d e " . Esto s i g n i f i c a normalmente que una t a b l a p a r t i c u l a r de s i s t e m a e s t l l e n a . Por ejemplo , e s t e e r r o r puede s e r generado por una l l a m a d a a f o r k cuando hay dema s i a d o s p r o c e s o s . /
20
2.12. fo_lee.c
2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38
E s t e programa l e e l o s mensajes e s c r i t o s en una FIFO y l o s muestra por p a n t a l l a . Funciona j u n t o con e l programa que e s c r i b e l o s mensajes en l a FIFO . Se debe e j e c u t a r en segundo p l a n o a n t e s que e l programa que e n v a l o s mensajes , siempre que a n t e s s e c r e e l a FIFO que s e u t i l i z a (" m k f i f o t u b o ") . /
#include < f c n t l . h> #include <s t d i o . h> #include < s t d l i b . h> #define MSGSIZ 63 char f i f o = " tubo " ; void f a t a l ( char s ) {
} perror ( s ) ; exit (1) ; main (
int
int
argc ,
char
argv [ ] ) {
if
for ( ; ; ) { if ( r e a d ( fd ,
} }
return
21
3.
PROCESOS
int pid = fork(). Crea un nuevo proceso (hijo del que hace la llamada a fork). Padre e hijo continan la ejecucin en la instruccin inmediatamente posterior al fork (VER FIGURA). pid = 0 en el hijo, >0 en el padre (y contiene el pid del hijo) y <0 si error exec. Se ejecuta en el espacio del proceso llamador (VER FIGURA). Posibilidades:
int execl(char *path, char *arg0, char *arg1,......, char *argn, NULL); int execv(char *path, char *argv[]); int execlp(char *file, char *arg0, char *arg1,......, char *argn, NULL); int execvp(char *file, char *argv[]);
Herencia en fork: el hijo hereda todas las variables del padre con los mismos valores (excepto
el valor que devuelve el fork), pero son independientes. Los cheros abiertos en el padre, lo estn en el hijo tambin se comparten (y, por tanto, el puntero del chero,....). No obstante, cerrar un chero en el padre no afecta a los del hijo, y viceversa.
defecto a o) con fcntl, para que se cierren automticamente tras al hacer el exec. Por ejemplo:
fcntl(fd,f_setfd,1);
Herencia en exec: deja los cheros abiertos. Se debe activar el ag close_on_exec (por
void exit(int estado). Para terminar un proceso. Tambin se termina al llegar al nal del
cdigo o con un return desde main. Se suele colocar exit(0) si ha habido xito o exit(!=0) si ha habido algn tipo de error. Los 8 bits bajos de un exit estn disponibles en el padre en los 8 bits altos (ver wait).
int resultado = wait(int *estado). Se utiliza en el padre para esperar a que terminen los
hijos.
Si como puntero se pasa NULL, se ignora el valor de estado. La funcin devuelve el pid del hijo que termina o -1 si ha habido error (no hay hijos,....). Si los 8 bits menos signicativos del estado tienen un valor distinto de 0 signica que el
22
Si son 0, en los 8 bits ms signicativos tenemos el valor que se coloc como parmetro
en el exit.
Zombie: hijo que hizo exit pero cuyo padre no ha hecho un wait. Hurfano: un padre puede terminar sin wait hijos adoptados por el proceso de inicializacin del sistema (init). int pid = getpid(). Devuelve el pid del proceso que la ejecuta. int pid_padre = getppid(). Devuelve el pid del padre.
Variables de entorno.
void main(int argc, char *argv[], char *envp[]);
void (*was) () = signal(int sig, void (*fun) ()). Captura la seal sig mediante la
funcin fun. Devuelve un puntero a la funcin que previamente capturaba sig. Tipos de seales:
SIGQUIT: Terminar. Muy similar a SIGINT. Enviada por el ncleo cuando se pulsa
la tecla de terminacin (CTRL-\). A diferencia de SIGINT, provoca una terminacin anormal (toda terminacin anormal provoca un core dump, es decir, un vaciado de memoria). SIGILL: Instruccin ilegal Terminacin anormal. SIGFPE: Error de punto otante Terminacin anormal. SIGKILL: Enviada por un proceso o por el ncleo a otro proceso para que termine forzosamente ste ltimo. No se puede capturar. SIGPIPE: Enviada por el ncleo cuando se escribe en una tubera que no tiene un proceso que lea. SIGALRM: Alarma. Enviada por el ncleo a un proceso transcurrido un cierto tiempo (ver la funcin ALARM). SIGTERM: Seal de terminacin software. Se utiliza para solicitar a un proceso que termine. No la enva el ncleo (ver KILL). SIGUSR1 y SIGUSR2: No las enva el ncleo y se pueden utilizar para lo que se quieran.
una funcin normal o las funciones SIG_IGN (simplemente hace que la seal se ignore) y SIG_DFL (que indica que se realice la accin por defecto asociada a la seal).
23
Si una seal no se captura Terminacin (normal o anormal, segn el tipo de seal) del proceso receptor. Se pueden tratar varios tipos de seales a la misma vez. Las seales ignoradas por un proceso (SIG_IGN) siguen ignoradas tras un exec. Qu pasa si un proceso en segundo plano no quiere que se ignoren? Hay llamadas al sistema que, excepcionalmente, son interrumpidas por una seal, como read, write,..... La funcin sigaction y otras funciones asociadas permiten un control total sobre las seales. Entre otras cosas, permite bloquear seales mientras se tratan otras, y si la rutina de tratamiento de una seal permanece instalada indenidamente o se desinstala tras recibir la seal. En el caso concreto de tratar la seal sigchld el parmetro sa_ags debe ser SA_RESTART | SA_SIGINFO, y la funcin callback tendr la forma:
void tratamiento(int nsig, siginfo_t* info, void*nada) { /* Acceso a info->si_pid, info->si_signo, etc.*/ /* (si_pid es el pid del proceso que enva la seal */ }
int kill(int pid, int sig). Permite enviar una seal de un proceso a otro, siempre que coincidan
sus UID (identicador de usuario) reales o efectivos. Los procesos de superusuario pueden enviar seales a cualquier otro. KILL devuelve -1 si:
No coinciden los UID's reales o efectivos. No existe el proceso. No existe ese tipo de seal.
unsigned int alarm(unsigned int seg). Hace que se enve una seal SIGALRM al proceso,
despus de seg segundos. Una alarma se desactiva con alarm(0). Devuelve los segundos que quedaban para que se cumpliera la anterior alarma. Una alarma permanece activa tras un exec pero no en un hijo, tras un fork.
int pause(void). Detiene temporalmente un proceso hasta que ste reciba una seal (siempre que no la ignore porque, entonces, pause tambin la ignorar). Devuelve -1 cuando la seal se captura. Un proceso suspendido temporalmente no consume recursos del sistema.
5. COMUNICACIONES ENTRE PROCESOS. TUBERAS
Es una generalizacin del concepto de chero ya que se utilizan las mismas rdenes read, write y close que se utilizan con cheros.
Una tubera (pipe) es un canal de comunicaciones unidireccional que conecta dos procesos. int pipe(int ledes[2]). Para crear la tubera. ledes[0] es el descriptor de chero de lectura
de la tubera y ledes[1] es el descriptor para la escritura en la tubera. lseek no funciona en una tubera. Los buers de lectura y escritura en la tubera pueden tener distinto tamao.
24
Tras un fork, el hijo tiene dos descriptores propios para la tubera. Conviene que cada uno cierre (close) el que no vaya a utilizar.
Bloqueos. Un write en una tubera se bloquea si est llena y un read se bloquea si est vaca
(aunque se puede hacer que tanto el write como el read sean no bloqueantes). Cerrar un extremo de una tubera:
Extremo de slo escritura: si hay ms procesos que escriban en la tubera, no pasa nada. Si no es as, a los procesos que lean de la tubera a partir de ese momento reciben del read un 0. Si haba procesos bloqueados porque la tubera estaba vaca, se les despierta del read, que devuelve tambin 0. Extremo de slo lectura: si hay ms procesos que lean de la tubera, no pasa nada. Si no es as, a todos los procesos que estn bloqueados en write o que intenten escribir a partir de ese momento, se les enva una seal SIGPIPE por el ncleo. Si capturan SIGPIPE, los siguientes writes devuelven -1.
de sus hijos). Este problema surge al intentar crear un servidor. No pueden ser permanentes. Diferencias:
Una FIFO o tubera nombrada (named pipe) funciona prcticamente igual que una tubera.
Es permanente. Tiene un nombre de chero, un propietario, un tamao y permisos. Se abre, se cierra y borrar igual que un chero.
Creacin de una FIFO: mkfo <nombre>. Tambin se puede utilizar la orden mknod
<nombre>p.
7. BIBLIOGRAFA
UNIX: programacin avanzada. Mrquez Garca, Fo Manuel. UNIX: sistema y entorno. Fontaine, A.B. UNIX system programing. Haviland, Keith.
25