Lab. di Sistemi Operativi
Esercitazioni proposte per la lezione del 27 maggio 2011
Utilizzando il compilatore gcc in Linux e disponendosi in gruppi di due persone per ogni PC del labora- torio.
1. Determinare con un programma c (es111.c) il segnale che causa la terminazione di un processo figlio quando questo tenta di scrivere su una pipe con lato di lettura chiuso (completamento dell’esercizio della scorsa settimana)
2. Modificare il precedente sorgente (in es112.c) in modo che il segnale di broken pipe (man 7 signal:
SIGPIPE,13,Broken pipe) venga intercettato da un opportuno handler.
3. (facoltativo)Ottenere un ritardo con l’uso del segnale SIGARLM. Progettare un applicativo che si sospenda per 10 secondi senza utilizzare la funzione sleep().
4. Progettare un applicativo concorrente con due processi (padre e figlio) che si alternano nella scrittura su stdout mediante segnali (es114.c)
Soluzione
Esercitazioni proposte per la lezione del 27 maggio 2011
Utilizzando il compilatore gcc in Linux e disponendosi in gruppi di due persone per ogni PC del labora- torio.
1. Determinare con un programma c (es111.c) il segnale che causa la terminazione di un processo figlio quando questo tenta di scrivere su una pipe con lato di lettura chiuso (completamento dell’esercizio della scorsa settimana)
Soluzione:
/∗ f i l e : e s 1 1 1 . c
∗ j o b : i d e n t i f i c a z i o n e d e l s e g n a l e b r o k e n p i p e
∗/
#include <u n i s t d . h>
#include <s t d i o . h>
#include < s t r i n g . h>
#include <s y s / t y p e s . h>
#include <s y s / w a i t . h>
char msg [ 2 5 6 ] ; char msg2 [ 2 5 6 ] ;
i n t main ( i n t a r g c , char ∗∗ a r g v ) {
i n t p f d [ 2 ] ; /∗ c o n t e n i t o r e p e r i 2 f d ∗/
i n t nw , nr ; /∗ r i t o r n i d i r e a d e w r i t e ∗/
i n t s t ;
i f ( p i p e ( p f d ) ! = 0 ) {
w r i t e ( 2 , ” E r r o r e i n p i p e ( ) \ n” , 1 7 ) ; return ( 1 ) ;
}
s n p r i n t f ( msg , s i z e o f ( msg ) , ” p f d [0]=%d , p f d [1]=%d\n” , p f d [ 0 ] ,
p f d [ 1 ] ) ;
w r i t e ( 1 , msg , s t r l e n ( msg ) ) ; /∗ su s t d o u t ∗/
c l o s e ( p f d [ 0 ] ) ; /∗ c h i u d o l a t o l e t t u r a ∗/
/∗ u t i l i z z i a m o l a f o r k p e r l a s c i a r e a l p r o c e s s o f i g l i o
∗ l ’ incombenza d i s c r i v e r e s u l l a p i p e e r e c u p e r i a m o
∗ l e i n f o r m a z i o n i d i t e r m i n a z i o n e con l a w a i t ∗/
switch ( f o r k ( ) ) {
case 0 : /∗ f i g l i o ∗/
nw=w r i t e ( p f d [ 1 ] , msg , s t r l e n ( msg ) ) ; /∗ su msg−>p i p e ∗/
/∗ q u e s t a s y s c a l l s c a t e n a un s e g n a l e d i
∗ ” b r o k e n p i p e ” che p r o v o c a l a t e r m i n a z i o n e d e l
∗ p r o c e s s o ∗/
nr=r e a d ( p f d [ 0 ] , msg2 , s i z e o f ( msg2 ) ) ; /∗ da p i p e −>msg2 ∗/
w r i t e ( 1 , msg2 , s t r l e n ( msg2 ) ) ; /∗ msg2 su s t d o u t ∗/
s n p r i n t f ( msg , s i z e o f ( msg ) , ”nw= %d , nr= %d\n” , nw , nr ) ;
w r i t e ( 1 , msg , s t r l e n ( msg ) ) ; /∗ su s t d o u t ∗/
return ( 0 ) ;
case −1: /∗ e r r o r e f o r k ∗/
w r i t e ( 2 , ” E r r o r e f o r k \n” , 1 2 ) ; /∗ su s t d e r r ∗/
return ( 1 ) ; break ;
}
/∗ p a d r e : a t t e n d o i l f i g l i o ( un ic o , non d e v o r e c u p e r a r e i l p i d ) ∗/
w a i t (& s t ) ;
i f (WIFEXITED( s t ) ) { /∗ t e r m i n a z i o n e ” n a t u r a l e ” , e x i t v a l u e v a l i d o ∗/
s n p r i n t f ( msg , s i z e o f ( msg ) , ” F i g l i o t o r n a %d\n” , WEXITSTATUS( s t ) ) ;
w r i t e ( 1 , msg , s t r l e n ( msg ) ) ;
} e l s e { /∗ t e r m i n a z i o n e f o r z a t a , no e x i t v a l u e ma i d s e g n a l e ∗/
s n p r i n t f ( msg , s i z e o f ( msg ) , ” F i g l i o t e r m i n a t o da %d\n” , WTERMSIG( s t ) ) ;
w r i t e ( 1 , msg , s t r l e n ( msg ) ) ; }
return ( 0 ) ; }
2. Modificare il precedente sorgente (in es112.c) in modo che il segnale di broken pipe (man 7 signal:
SIGPIPE,13,Broken pipe) venga intercettato da un opportuno handler.
Soluzione:
/∗ f i l e : e s 1 1 2 . c
∗ j o b : i n t e r c e t t a m e n t o d e l s e g n a l e b r o k e n p i p e
∗/
#include <u n i s t d . h>
#include <s t d i o . h>
#include < s t r i n g . h>
#include <s y s / t y p e s . h>
#include <s y s / w a i t . h>
#include < s i g n a l . h>
char msg [ 2 5 6 ] ; char msg2 [ 2 5 6 ] ;
/∗ p r o t o t i p o d e l l ’ h a n d l e r ∗/
void i n t e r c e t t a ( i n t s e g n a l e ) ; i n t main ( i n t a r g c , char ∗∗ a r g v ) {
i n t p f d [ 2 ] ; /∗ c o n t e n i t o r e p e r i 2 f d ∗/
i n t nw , nr ; /∗ r i t o r n i d i r e a d e w r i t e ∗/
i n t s t ;
i f ( p i p e ( p f d ) ! = 0 ) {
w r i t e ( 2 , ” E r r o r e i n p i p e ( ) \ n” , 1 7 ) ; return ( 1 ) ;
}
s n p r i n t f ( msg , s i z e o f ( msg ) , ” p f d [0]=%d , p f d [1]=%d\n” , p f d [ 0 ] ,
p f d [ 1 ] ) ;
w r i t e ( 1 , msg , s t r l e n ( msg ) ) ; /∗ su s t d o u t ∗/
c l o s e ( p f d [ 0 ] ) ; /∗ c h i u d o l a t o l e t t u r a ∗/
/∗ u t i l i z z i a m o l a f o r k p e r l a s c i a r e a l p r o c e s s o f i g l i o
∗ l ’ incombenza d i s c r i v e r e s u l l a p i p e e r e c u p e r i a m o
∗ l e i n f o r m a z i o n i d i t e r m i n a z i o n e con l a w a i t ∗/
switch ( f o r k ( ) ) {
case 0 : /∗ f i g l i o ∗/
/∗ a g g a n c i o i n t e r c e t t a ( ) a SIGPIPE ∗/
s i g n a l ( SIGPIPE , i n t e r c e t t a ) ;
nw=w r i t e ( p f d [ 1 ] , msg , s t r l e n ( msg ) ) ; /∗ su msg−>p i p e ∗/
/∗ q u e s t a s y s c a l l s c a t e n a un s e g n a l e d i
∗ ” b r o k e n p i p e ” che p r o v o c a l a t e r m i n a z i o n e d e l
∗ p r o c e s s o ∗/
nr=r e a d ( p f d [ 0 ] , msg2 , s i z e o f ( msg2 ) ) ; /∗ da p i p e −>msg2 ∗/
w r i t e ( 1 , msg2 , s t r l e n ( msg2 ) ) ; /∗ msg2 su s t d o u t ∗/
s n p r i n t f ( msg , s i z e o f ( msg ) , ”nw= %d , nr= %d\n” , nw , nr ) ;
w r i t e ( 1 , msg , s t r l e n ( msg ) ) ; /∗ su s t d o u t ∗/
return ( 0 ) ;
case −1: /∗ e r r o r e f o r k ∗/
w r i t e ( 2 , ” E r r o r e f o r k \n” , 1 2 ) ; /∗ su s t d e r r ∗/
return ( 1 ) ; break ; }
/∗ p a d r e : a t t e n d o i l f i g l i o ( un ic o , non d e v o r e c u p e r a r e i l p i d ) ∗/
w a i t (& s t ) ;
i f (WIFEXITED( s t ) ) { /∗ t e r m i n a z i o n e ” n a t u r a l e ” , e x i t v a l u e v a l i d o ∗/
s n p r i n t f ( msg , s i z e o f ( msg ) , ” F i g l i o t o r n a %d\n” , WEXITSTATUS( s t ) ) ;
w r i t e ( 1 , msg , s t r l e n ( msg ) ) ;
} e l s e { /∗ t e r m i n a z i o n e f o r z a t a , no e x i t v a l u e ma i d s e g n a l e ∗/
s n p r i n t f ( msg , s i z e o f ( msg ) , ” F i g l i o t e r m i n a t o da %d\n” , WTERMSIG( s t ) ) ;
w r i t e ( 1 , msg , s t r l e n ( msg ) ) ; }
return ( 0 ) ; }
void i n t e r c e t t a ( i n t s e g n a l e ) {
s n p r i n t f ( msg , s i z e o f ( msg ) , ” F i g l i o : i n t e r c e t t o %d\n” , s e g n a l e ) ;
w r i t e ( 1 , msg , s t r l e n ( msg ) ) ; return ;
}
3. (facoltativo)Ottenere un ritardo con l’uso del segnale SIGARLM. Progettare un applicativo che si sospenda per 10 secondi senza utilizzare la funzione sleep().
Soluzione:
/∗ f i l e : e s 1 1 3 . c
∗ j o b : a t t e s a t e m p o r i z z a t a
∗/
#include < s i g n a l . h>
#include <s t d i o . h>
#include <u n i s t d . h>
#include < s t r i n g . h>
#include <s e t j m p . h>
void s i g f u n ( i n t s i g i d ) ; char msg [ 2 5 6 ] ;
j m p b u f s t a t o ; /∗ s a l v a t a g g i o s t a t o ∗/
i n t main ( i n t a r g c , char ∗∗ a r g v ) {
/∗ c o l l e g h i a m o SIGALRM a l l a n o s t r a s i g f u n ∗/
s i g n a l (SIGALRM, s i g f u n ) ; i f ( s e t j m p ( s t a t o ) ) {
/∗ s e non z e r o , a l l o r a t o r n o ∗/
s n p r i n t f ( msg , s i z e o f ( msg ) ,
” A t t e s a s c a d u t a \n” ) ; w r i t e ( 1 , msg , s t r l e n ( msg ) ) ; } e l s e {
/∗ s e z e r o , primo p a s s a g g i o ∗/
s n p r i n t f ( msg , s i z e o f ( msg ) ,
” A t t e s a i n i z i a t a \n” ) ; w r i t e ( 1 , msg , s t r l e n ( msg ) ) ; alarm ( 1 0 ) ;
s n p r i n t f ( msg , s i z e o f ( msg ) ,
” S v e g l i a i m p o s t a t a \n” ) ; w r i t e ( 1 , msg , s t r l e n ( msg ) ) ; f o r ( ; ; ) {
p a u s e ( ) ; }
}
return ( 0 ) ; }
void s i g f u n ( i n t s i g i d ) { i f ( s i g i d==SIGALRM) {
longjmp ( s t a t o , 1 ) ; }
}
4. Progettare un applicativo concorrente con due processi (padre e figlio) che si alternano nella scrittura su stdout mediante segnali (es114.c)
Soluzione:
Parent
Figlio
SIGUSR1 SIGUSR1
/∗ f i l e : e s 1 1 4 . c
∗ j o b : s i n c r o n i z z a z i o n e con s e g n a l i
∗/
#include < s i g n a l . h>
#include <s t d i o . h>
#include <u n i s t d . h>
#include <s y s / t y p e s . h>
#include < s t r i n g . h>
void s i g f u n ( i n t s i g i d ) ; i n t f i g l i o ( void ) ;
v o l a t i l e i n t c o n s e n s o ; char msg [ 2 5 6 ] ;
i n t main ( i n t a r g c , char ∗∗ a r g v ) { p i d t p i d f i g l i o ;
/∗ c o l l e g h i a m o SIGUSR1 a l l a n o s t r a s i g f u n ∗/
s i g n a l ( SIGUSR1 , s i g f u n ) ;
c o n s e n s o =0; /∗ c o n s e n s o a s s e n t e ∗/
switch ( p i d f i g l i o =f o r k ( ) ) { case 0 : /∗ f i g l i o ∗/
return ( f i g l i o ( ) ) ; case −1: /∗ e r r o r e ∗/
s n p r i n t f ( msg , s i z e o f ( msg ) ,
” E r r o r e f o r k ( ) \ n” ) ; w r i t e ( 2 , msg , s t r l e n ( msg ) ) ; return ( 1 ) ;
}
/∗ p a d r e ∗/
c o n s e n s o =1; /∗ i l p a d r e i n i z i a ∗/
f o r ( ; ; ) {
s n p r i n t f ( msg , s i z e o f ( msg ) , ” Padre \n” ) ; while ( ! c o n s e n s o ) p a u s e ( ) ;
w r i t e ( 1 , msg , s t r l e n ( msg ) ) ; s l e e p ( 1 ) ; /∗ r a l l e n t a t o r e ! ∗/
c o n s e n s o =0; /∗ mi b l o c c o ∗/
k i l l ( p i d f i g l i o , SIGUSR1 ) ; /∗ s b l o c c o ∗/
}
return ( 0 ) ; }
i n t f i g l i o ( ) { f o r ( ; ; ) {
s n p r i n t f ( msg , s i z e o f ( msg ) , ” F i g l i o \n” ) ; while ( ! c o n s e n s o ) p a u s e ( ) ;
w r i t e ( 1 , msg , s t r l e n ( msg ) ) ; s l e e p ( 1 ) ; /∗ r a l l e n t a t o r e ! ∗/
c o n s e n s o =0; /∗ mi b l o c c o ∗/
k i l l ( g e t p p i d ( ) , SIGUSR1 ) ; /∗ s b l o c c o ∗/
}
return ( 0 ) ; }
void s i g f u n ( i n t s i g i d ) { i f ( s i g i d==SIGUSR1 ) {
c o n s e n s o =1;
} }