Lab. di Sistemi Operativi
Esercitazioni proposte per la lezione del 20 maggio 2011
Utilizzando il compilatore gcc in Linux e disponendosi in gruppi di due persone per ogni PC del labora- torio.
1. (45 minuti) es101.c Soluzione al compito del 8 aprile 2005
La parte in C accetta un numero variabile di parametri che rappresentano nomi di file F1...FM e un numero K strettamente positivo, pari e strettamente minore di 7 che rappresenta il numero di linee di ogni file. Il processo padre deve generare M processi figli (P1..PM): ogni processo figlio associato ad uno dei file Fi. Ognuno di tali processi figli deve creare un file il cui nome (FiK) risulti dalla concatenazione del nome del file associato (Fi) con la stringa che corrisponde al numero K; quindi, ogni figlio deve creare un processo nipote: la coppia figlio e nipote esegue concorrentemente leggendo, rispettivamente, il figlio le linee dispari e il nipote le linee pari. Il processo nipote, dopo la lettura di ogni linea pari, calcola la sua lunghezza (LP) e la comunica al processo figlio; il processo figlio, dopo la lettura di ogni linea dispari, calcola la sua lunghezza (LD) e riceve dal nipote LP: se LD minore di LP, allora il processo figlio scrive la sua linea sul file FiK(*) . Ogni processo figlio deve ritornare al padre il numero di linee scritte sul file FiK.
Il padre, dopo che i figli sono terminati, deve stampare su standard output i PID di ogni figlio con il corrispondente valore ritornato.
(*) Le letture dal singolo file da parte di una coppia di processi figlio-nipote non devono essere sin- cronizzate.
2. (45 minuti) es102.c Soluzione al compito del 12 marzo 2004
La parte in C accetta un numero variabile di parametri che rappresentano un nome di file F e N caratteri C1 ... CN. Il processo padre deve generare N processi figli (P1..PN): ogni processo figlio
`
e associato ad uno dei caratteri Ci. Ognuno di tali processi figli esegue concorrentemente e verifica se il file F contiene il carattere associato Ci; in particolare, ogni processo figlio deve riportare sullo standard output il numero d’ordine di ogni linea di F che contiene il carattere associato. La scrittura dei processi figli deve essere sincronizzata (senza l’intervento del padre) affinch´e venga stampata prima una informazione di P1, poi di P2, e cos via fino a PN, dopodich´e si ricomincia da P1 finch´e tutti i processi non hanno verificato tutto il file. Al termine, ogni processo figlio deve ritornare al padre il numero di linee che contengono il carattere associato. Il padre visualizza su standard output i valori ritornati dai figli.
NOTA BENE:
Si consideri ipotizzabile che i processi figli terminano in cascata, dal primo all’ultimo.
3. Invertire l’ordine di sincronizzazione dei figli nell’esercizio es102.c (es103.c)
4. Creiamo un sorgente C es104.c che possa servire come base di partenza per la realizzazione di appli- cazioni concorrenti.
5. Creiamo un Makefile per la compilazione dell’esempio
Soluzione
Esercitazioni proposte per la lezione del 20 maggio 2011
Utilizzando il compilatore gcc in Linux e disponendosi in gruppi di due persone per ogni PC del labora- torio.
1. (45 minuti) es101.c Soluzione al compito del 8 aprile 2005
La parte in C accetta un numero variabile di parametri che rappresentano nomi di file F1...FM e un numero K strettamente positivo, pari e strettamente minore di 7 che rappresenta il numero di linee di ogni file. Il processo padre deve generare M processi figli (P1..PM): ogni processo figlio associato ad uno dei file Fi. Ognuno di tali processi figli deve creare un file il cui nome (FiK) risulti dalla concatenazione del nome del file associato (Fi) con la stringa che corrisponde al numero K; quindi, ogni figlio deve creare un processo nipote: la coppia figlio e nipote esegue concorrentemente leggendo, rispettivamente, il figlio le linee dispari e il nipote le linee pari. Il processo nipote, dopo la lettura di ogni linea pari, calcola la sua lunghezza (LP) e la comunica al processo figlio; il processo figlio, dopo la lettura di ogni linea dispari, calcola la sua lunghezza (LD) e riceve dal nipote LP: se LD minore di LP, allora il processo figlio scrive la sua linea sul file FiK(*) . Ogni processo figlio deve ritornare al padre il numero di linee scritte sul file FiK.
Il padre, dopo che i figli sono terminati, deve stampare su standard output i PID di ogni figlio con il corrispondente valore ritornato.
(*) Le letture dal singolo file da parte di una coppia di processi figlio-nipote non devono essere sin- cronizzate.
Soluzione:
Parent
pfn pfn
F[0] F[1]
N[0] N[1] N[M−1]
pfn
F[M−1]
wait()
wait() wait()
/∗ f i l e : e s 1 0 1 . c
∗ j o b : s o l u z i o n e 8 a p r i l e 2005
∗/
#include <s t d i o . h>
#include < s t d l i b . h>
#include <u n i s t d . h>
#include <s y s / w a i t . h>
#include < f c n t l . h>
#include <s t d a r g . h>
i n t M; /∗ numero d i p r o c e s s i f i g l i ∗/
i n t K; /∗ u l t i m o argomento ∗/
p i d t p i d ; /∗ a p p o g g i o p e r v a l o r e p i d ∗/
i n t s t a t u s ; /∗ a p p o g g i o p e r w a i t ∗/
i n t p f n [ 2 ] ; /∗ p i p e f i g l i o −n i p o t e , a t t e n z i o n e o g n i p r o c e s s o f i g l i o ha l a sua i s t a n z a d i q u e s t a v a r i a b i l e q u i n d i l e p i p e c r e a t e sono ”M” ∗/
i n t f d r , fdw ; /∗ f i l e d e s c r i p t o r s p e r r e a d e w r i t e ∗/
i n t i n d i c e ; /∗ i n d i c e su l i n e a ∗/
char l i n e a [ 2 5 6 ] ; /∗ b u f f e r d i l i n e a ∗/
char FiK [ 8 0 ] ; /∗ nome f i l e d i u s c i t a ∗/
i n t LP , LD ; /∗ l u n g h e z z e l i n e a ∗/
i n t l i n e a c o r r ; /∗ l i n e a c o r r e n t e ∗/
i n t n o n s c r i t t e ; /∗ numero d i l i n e e non s c r i t t e ∗/
/∗ a b b i n a m e n t o s n p r i n t f+w r i t e ∗/
void z p r i n t f ( i n t fd , const char ∗ fmt , . . . ) ; /∗ f u n z i o n e f i g l i o ∗/
i n t f i g l i o ( char ∗ f i l e n a m e , i n t i ) ; /∗ f u n z i o n e n i p o t e ∗/
i n t n i p o t e ( char ∗ f i l e n a m e , i n t i ) ; i n t main ( i n t a r g c , char ∗∗ a r g v ) {
i n t i ; /∗ i n t d i a p p o g g i o ∗/
/∗ c o n t r o l l o numero d i a r g o m e n t i ∗/
i f ( a r g c <3) {
z p r i n t f ( 2 , ” E r r o r e n e l numero d i a r g o m e n t i \n” ) ; return ( 1 ) ;
}
M=a r g c −2; /∗ numero d i p r o c e s s i f i g l i ∗/
K=a t o i ( a r g v [ a r g c − 1 ] ) ; /∗ numero K, u l t i m o argomento ∗/
i f ( (K< = 0 ) | | (K> = 7 ) | | ( (K%2)!=0)) {
z p r i n t f ( 2 , ” Parametro K non v a l i d o : %d\n” ,K ) ; return ( 2 ) ;
}
/∗ c r e a z i o n e f i g l i e a t t r i b u z i o n e a r g o m e n t i ∗/
f o r ( i =0; i <M; i ++) { switch ( f o r k ( ) ) {
case 0 : /∗ f i g l i o ∗/
return ( f i g l i o ( a r g v [ i + 1 ] , i ) ) ; case −1:
/∗ e r r o r e ∗/
z p r i n t f ( 2 , ” E r r o r e n e l l a %d f o r k \n” , i ) ; return ( 3 ) ;
} }
/∗ r e c u p e r o e x i t s t a t u s d e i f i g l i ( non d e i n i p o t i ) ∗/
f o r ( i =0; i <M; i ++) { p i d=w a i t (& s t a t u s ) ;
i f (WIFEXITED( s t a t u s ) ) { z p r i n t f ( 1 ,
” I l f i g l i o con p i d %d r i t o r n a %d\n” , pid , WEXITSTATUS( s t a t u s ) ) ;
} e l s e {
z p r i n t f ( 1 ,
” I l f i g l i o con p i d %d e ’ t e r m i n a t o p e r i l s e g n a l e %d\n” , pid , WTERMSIG( s t a t u s ) ) ;
} }
return ( 0 ) ; }
void z p r i n t f ( i n t fd , const char ∗ fmt , . . . ) { /∗ p r i n t f wrapper u s i n g w r i t e i n s t e a d ∗/
s t a t i c char msg [ 2 5 6 ] ; v a l i s t ap ;
i n t n ;
v a s t a r t ( ap , fmt ) ;
n=v s n p r i n t f ( msg , 2 5 6 , fmt , ap ) ; w r i t e ( fd , msg , n ) ;
v a e n d ( ap ) ; }
i n t f i g l i o ( char ∗ f i l e n a m e , i n t i ) { char ch ;
/∗ c r e o l a p i p e f i g l i o −n i p o t e ∗/
i f ( p i p e ( p f n ) ! = 0 ) {
z p r i n t f ( 2 , ” E r r o r e c r e a z i o n e p i p e f i g l i o −n i p o t e %d\n” , i ) ; a b o r t ( ) ; /∗ t e r m i n o p e r SIGABRT, i l p a d r e s e ne a c c o r g e ∗/
return ( 4 ) ; }
/∗ c r e o i l n i p o t e ∗/
switch ( f o r k ( ) ) { case 0 :
return ( n i p o t e ( f i l e n a m e , i ) ) ; case −1:
/∗ e r r o r e ∗/
z p r i n t f ( 2 , ” E r r o r e n e l l a %d f o r k ( n i p o t e ) \ n” , i ) ; a b o r t ( ) ;
}
c l o s e ( p f n [ 1 ] ) ; /∗ non s c r i v o mai ∗/
/∗ l e g g e l e l i n e e 1 , 3 , . . . e v i t a n d o q u e l l e p a r i ∗/
f d r=open ( f i l e n a m e ,O RDONLY ) ; i f ( f d r <0) {
z p r i n t f ( 2 , ” I m p o s s i b i l e a p r i r e %s \n” , f i l e n a m e ) ; a b o r t ( ) ;
}
s n p r i n t f ( FiK , s i z e o f ( FiK ) , ”%s%d” , f i l e n a m e ,K) ;
#i f d e f DEBUG
z p r i n t f ( 1 , ” C r e a t o %s \n” , FiK ) ;
#endif
fdw=open ( FiK ,O WRONLY| O CREAT | O EXCL, 0 6 6 6 ) ; i f ( fdw <0) {
z p r i n t f ( 2 , ” I m p o s s i b i l e a p r i r e %s \n” , FiK ) ; a b o r t ( ) ;
}
l i n e a c o r r =1;
i n d i c e =0;
f o r ( ; ; ) {
i f ( r e a d ( f d r ,& ch , 1 ) ! = 1 ) { return ( n o n s c r i t t e ) ; }
#i f d e f DEBUG1
z p r i n t f ( 1 , ” Char %d\n” , ch ) ;
#endif
i f ( ch== ’ \n ’ ) { /∗ f i n e l i n e a ∗/
i f ( ( l i n e a c o r r %2)==1) { LD=i n d i c e ;
/∗ a t t e n d o i n f o da n i p o t e ∗/
#i f d e f DEBUG
z p r i n t f ( 1 , ” Attendo i n f o p e r l i n e a %d l u n g %d\n” , l i n e a c o r r , LD ) ;
#endif
i f ( r e a d ( p f n [ 0 ] , & LP , s i z e o f (LP) ) ! = s i z e o f (LP ) ) { z p r i n t f ( 2 , ” E r r o r e l e t t u r a p i p e \n” ) ;
a b o r t ( ) ; }
i f (LD>LP) {
w r i t e ( fdw , l i n e a , LD ) ;
w r i t e ( fdw , ” \n” , 1 ) ; /∗ f i n e l i n e a ∗/
} e l s e {
n o n s c r i t t e ++;
} }
i n d i c e =0;
l i n e a c o r r ++;
} e l s e i f ( ( l i n e a c o r r %2)==1) { /∗ l i n e a d i s p a r i , memorizzo ∗/
i f ( i n d i c e <s i z e o f ( l i n e a ) ) { l i n e a [ i n d i c e ++]=ch ; }
} }
/∗ f i n e f i g l i o , mai q u i ∗/
a b o r t ( ) ; return ( 0 ) ; }
i n t n i p o t e ( char ∗ f i l e n a m e , i n t i ) { char ch ;
/∗ n i p o t e , l i n e e p a r i ∗/
f d r=open ( f i l e n a m e ,O RDONLY ) ; i f ( f d r <0) {
z p r i n t f ( 2 , ” I m p o s s i b i l e a p r i r e %s \n” , f i l e n a m e ) ; return ( 1 ) ; /∗ r e c u p e r a b i l e con w a i t d a l f i g l i o ∗/
}
l i n e a c o r r =1;
i n d i c e =0;
f o r ( ; ; ) {
i f ( r e a d ( f d r ,& ch , 1 ) ! = 1 ) { /∗ f i n e f i l e ∗/
return ( 0 ) ; }
i f ( ch== ’ \n ’ ) { /∗ f i n e l i n e a ∗/
i f ( ( l i n e a c o r r %2)==0) { LP=i n d i c e ;
w r i t e ( p f n [ 1 ] , & LP , s i z e o f (LP ) ) ;
#i f d e f DEBUG
z p r i n t f ( 1 , ” I n v i a t a l u n g l i n e a %d , p a r i a %d\n” , l i n e a c o r r , LP ) ;
#endif
}
i n d i c e =0;
l i n e a c o r r ++;
} e l s e { i n d i c e ++;
} }
return ( 0 ) ; }
2. (45 minuti) es102.c Soluzione al compito del 12 marzo 2004
La parte in C accetta un numero variabile di parametri che rappresentano un nome di file F e N caratteri C1 ... CN. Il processo padre deve generare N processi figli (P1..PN): ogni processo figlio
`
e associato ad uno dei caratteri Ci. Ognuno di tali processi figli esegue concorrentemente e verifica se il file F contiene il carattere associato Ci; in particolare, ogni processo figlio deve riportare sullo standard output il numero d’ordine di ogni linea di F che contiene il carattere associato. La scrittura dei processi figli deve essere sincronizzata (senza l’intervento del padre) affinch´e venga stampata prima una informazione di P1, poi di P2, e cos via fino a PN, dopodich´e si ricomincia da P1 finch´e tutti i processi non hanno verificato tutto il file. Al termine, ogni processo figlio deve ritornare al padre il numero di linee che contengono il carattere associato. Il padre visualizza su standard output i valori ritornati dai figli.
NOTA BENE:
Si consideri ipotizzabile che i processi figli terminano in cascata, dal primo all’ultimo.
Soluzione:
/∗ f i l e : e s 1 0 2 . c
∗ j o b : s o l u z i o n e 12 marzo 2004
∗/
#include <s t d i o . h>
#include < s t d l i b . h>
#include <u n i s t d . h>
#include <s y s / t y p e s . h>
#include <s y s / w a i t . h>
#include <s y s / s t a t . h>
#include < f c n t l . h>
#include <s t d a r g . h>
typedef i n t p i p e t [ 2 ] ; /∗ t i p o p e r p i p e ∗/
#define SCRIT 1
#define LETT 0
char ∗F ; /∗ Nome d e l f i l e , v a r i a b i l e g l o b a l e ∗/
i n t N; /∗ Numero d i c a r a t t e r i ∗/
char ∗C ; /∗ E l e n c o d e i c a r a t t e r i , a l l o c a z i o n e d i n a m i c a ∗/
F[0] F[1] F[N−1]
pipes[N−1]
pipes[1] pipes[2]
pipes[0]
F[1] F[N−1]
F[1]
Parent
pipes[N−1]
pipes[2]
pipes[0]
pipes[2]
N wait()
i n t Npipe ; /∗ Numero d i p i p e da c r e a r e ∗/
p i p e t ∗ P f d s ; /∗ Array d i p i p e , a l l o c a z i o n e d i n a m i c a ∗/
i n t N f i g l i ; /∗ Numero d i f i g l i da f o r k a r e ∗/
i n t ∗ P i d s ; /∗ Array d i p i d , a l l o c a z i o n e d i n a m i c a ∗/
/∗ a b b i n a m e n t o s n p r i n t f+w r i t e ∗/
void z p r i n t f ( i n t fd , const char ∗ fmt , . . . ) ; /∗ f u n z i o n e f i g l i o ∗/
i n t f i g l i o ( i n t ) ;
char ok= ’Q ’ ; /∗ c a r a t t e r e ( c a s u a l e ) c h e i n v i a m o s u l l a p i p e p e r l a s i n c r o n i z z a z i o n e ∗/
i n t main ( i n t a r g c , char ∗∗ argv , char ∗∗ envp ) { i n t i , j ; /∗ q u a l c h e c o n t a t o r e ∗/
/∗ D e t e r m i n a z i o n e d e i d a t i d a l l a command l i n e ∗/
switch ( a r g c ) { case 0 : case 1 : case 2 :
z p r i n t f ( 2 , ” I n s e r i r e i l nome d i f i l e ed almeno un c a r a t t e r e \n” ) ; return ( 1 ) ;
}
F = a r g v [ 1 ] ;
N = a r g c −2; /∗ a r g c v a l e 1 s e non c i sono a r g o m e n t i ∗/
C = m a l l o c (N∗ s i z e o f ( char ) ) ; i f (C==NULL) {
z p r i n t f ( 2 , ” I m p o s s i b i l e a l l o c a r e C\n” ) ; return ( 1 ) ;
}
f o r ( i =0; i <N; i ++) {
C [ i ]= a r g v [ i + 2 ] [ 0 ] ; /∗ p r e n d o i l primo c a r a t t e r e d e l l a s t r i n g a a r g v [ i +2] ∗/
}
#i f d e f DEBUG
z p r i n t f ( 1 , ”Nome d e l f i l e : %s \n” ,F ) ; z p r i n t f ( 1 , ”Numero d i c a r a t t e r i %d\n” ,N ) ; f o r ( i =0; i <N; i ++) {
z p r i n t f ( 1 , ” C a r a t t e r e d i i n d i c e %d = %c \n” , i , C [ i ] ) ; }
#endif
/∗ P r e d i s p o s i z i o n e d e l s i s t e m a d i s i n c r o n i z z a z i o n e
∗ f r a i p r o c e s s i f i g l i : s i u t i l i z z a una p i p e p e r
∗ c o l l e g a r e o g n i f i g l i o a l s u c c e s s i v o ; l a s i n c r o n i z z a z i o n e
∗ d e l f i g l i o d i i n d i c e ’ k ’ s i o t t i e n e a t t e n d e n d o un
∗ c a r a t t e r e d a l l a p i p e che l o c o l l e g a a l f i g l i o d i
∗ i n d i c e ’ k −1 ’. ∗/
Npipe = N; /∗ una p i p e i n u s c i t a da o g n i f i g l i o ∗/
P f d s = m a l l o c ( Npipe ∗ s i z e o f ( p i p e t ) ) ; i f ( P f d s==NULL) {
z p r i n t f ( 2 , ” I m p o s s i b i l e a l l o c a r e P f d s \n” ) ; return ( 1 ) ;
}
f o r ( i =0; i <Npipe ; i ++) { i f ( p i p e ( P f d s [ i ] ) ! = 0 ) {
z p r i n t f ( 2 , ” I m p o s s i b i l e c r e a r e l a p i p e %d\n” , i ) ; return ( 1 ) ;
} }
/∗ C r e a z i o n e p r o c e s s i f i g l i :
∗ d a l t e s t o , b i s o g n a c r e a r e un p r o c e s s o f i g l i o p e r o g n i c a r a t t e r e
∗ q u i n d i N f i g l i=N
∗ V i s t o che i l p a d r e d e v e stampare i v a l o r i d i u s c i t a d e i p r o c e s s i
∗ f i g l i , s i devono memorizzare i p i d i n o r d i n e d i i n d i c e p e r p o i
∗ a b b i n a r e i r i s u l t a t i d e l l e w a i t . L ’ a r r a y d i p i d d e v e e s s e r e
∗ a l l o c a t o dinamicamente ∗/
N f i g l i = N;
P i d s=m a l l o c ( N f i g l i ∗ s i z e o f ( i n t ) ) ; i f ( P i d s==NULL) {
z p r i n t f ( 2 , ” I m p o s s i b i l e a l l o c a r e P i d s \n” ) ; return ( 1 ) ;
}
f o r ( i =0; i <N f i g l i ; i ++) { P i d s [ i ]= f o r k ( ) ;
switch ( P i d s [ i ] ) {
case 0 : /∗ f i g l i o d i i n d i c e i ∗/
return ( f i g l i o ( i ) ) ; /∗ chiamo f u n z i o n e f i g l i o e uso v a l o r e d i r i t o r n o come e x i t d e l p r o c e s s o ∗/
case −1:
z p r i n t f ( 2 , ” I m p o s s i b i l e f o r k a r e i l p r o c e s s o %d\n” , i ) ; return ( 1 ) ;
break ; }
#i f d e f DEBUG
/∗ s o l o i l p r o c e s s o p a d r e e s e g u e q u e s t e l i n e e ∗/
z p r i n t f ( 1 , ” F o r k a t o p r o c e s s o %d p e r i n d i c e %d\n” , P i d s [ i ] , i ) ;
#endif }
/∗ I l p a d r e non u t i l i z z a n e s s u n a p i p e i n quando l a s i n c r o n i z z a z i o n e
∗ v i e n e f a t t a t o t a l m e n t e f r a i f i g l i . E v e n t u a l m e n t e (ma c i sono
∗ anche a l t r i modi ) i l p a d r e puo ’ d a r e i l v i a a l primo f i g l i o .
∗ U t i l i z z i a m o q u e s t a p o s s i b i l i t a ’ ed u t i l i z z i a m o un s i n g o l o
∗ c a r a t t e r e memorizzato i n ok p e r l ’ i n v i o ∗/
i f ( w r i t e ( P f d s [ 0 ] [ SCRIT] , & ok , 1 ) ! = 1 ) { /∗ c o n t r o l l o d i s c r i t t u r a a v v e n u t a ∗/
z p r i n t f ( 2 , ” I m p o s s i b i l e i n v i a r e su %d\n” , P f d s [ 0 ] [ SCRIT ] ) ; return ( 1 ) ;
}
/∗ o r a c h i u d i a m o t u t t e l e p i p e i n u t i l i z z a t e d a l padre , compresa
∗ q u e l l a i n c u i abbiamo appena s c r i t t o ( i l c a r a t t e r e rimane ! ) ∗/
f o r ( i =0; i <Npipe ; i ++) { c l o s e ( P f d s [ i ] [ SCRIT ] ) ; c l o s e ( P f d s [ i ] [ LETT ] ) ; }
/∗ Recupero d e l l e i n f o r m a z i o n i d a i p r o c e s s i f i g l i t r a m i t e l a w a i t ∗/
f o r ( i =0; i <N f i g l i ; i ++) { i n t p i d x ;
i n t s t a t u s ;
p i d x = w a i t (& s t a t u s ) ;
/∗ a b b i n a m e n t o d e l l e i n f o r m a z i o n i a l l ’ i n d i c e d e l f i g l i o ∗/
f o r ( j =0; j <N f i g l i ; j ++) { i f ( p i d x==P i d s [ j ] ) {
i f (WEXITSTATUS( s t a t u s )==255) {
/∗ c o n v e n z i o n e : s e g n a l a z i o n e d ’ e r r o r e ∗/
z p r i n t f ( 1 ,
” I l f i g l i o c h e c e r c a i l c a r a t t e r e %c ha i n c o n t r a t o un e r r o r e \n” , C [ j ] ) ;
} e l s e {
z p r i n t f ( 1 ,
” I l f i g l i o c h e c e r c a i l c a r a t t e r e %c ha t r o v a t o %d l i n e e \n” , C [ j ] ,WEXITSTATUS( s t a t u s ) ) ;
} } } }
return ( 0 ) ; }
/∗ F un z io n e f i g l i o ∗/
i n t f i g l i o ( i n t i n d i c e ) {
/∗ Ogni f i g l i o d e v e c e r c a r e l e o c c o r r e n z e d i C[ i ] n e l f i l e F ,
∗ q u i n d i i l f i l e NON d e v e e s s e r e c o n d i v i s o ma a p e r t o i n d i p e n d e n t e m e n t e
∗ da o g n i f i g l i o ∗/
i n t f d ;
i n t linenum ; /∗ c o n t a t o r e d i l i n e a c o r r e n t e ∗/
char ch ; /∗ c a r a t t e r e d i a p p o g g i o ∗/
i n t r e t v a l ; /∗ v a l o r e d i r i t o r n o ∗/
i n t nr ; /∗ numero d i c a r a t t e r i l e t t i d a l l a r e a d ∗/
i n t f l a g ; /∗ s e 0 c a r a t t e r e non t r o v a t o , s e 1 t r o v a t o ∗/
i n t nrp ; /∗ numero d i c a r l e t t i da r e a d su p i p e ∗/
char dummy ; /∗ c a r a t t e r e d i a p p o g g i o p e r l e t t / s c r i t t p i p e ∗/
i n t i ; /∗ un c o n t a t o r e ∗/
i n t p i p e d i s i n c ; /∗ i n d i c e d e l l a p i p e d i s i n c r o n i z z a z i o n e da c u i f a r e l a r e a d ∗/
/∗ C h i u s u r a d e i l a t i d e l l e p i p e p e r e v i t a r e i l d e a d l o c k quando
∗ un f i g l i o t e r m i n a prima d e g l i a l t r i e non puo ’ p r o s e g u i r e
∗ n e l l ’ a t t i v i t a ’ d i s i n c r o n i z z a z i o n e . Se almeno i l a t i
∗ d i s c r i t t u r a sono p o s s e d u t i ognuno da un s o l o p r o c e s s o
∗ l a t e r m i n a z i o n e d i q u e s t o p r o v o c a un comportamento non
∗ b l o c c a n t e p e r l a r e a d ∗/
f o r ( i =0; i <Npipe ; i ++) {
/∗ c h i u d o i l a t i d i s c r i t t u r a s e non e ’ l a p i p e
∗ che usa q u e s t o f i g l i o ∗/
i f ( i n d i c e != N f i g l i −1) { i f ( i ! = ( i n d i c e +1)) {
c l o s e ( P f d s [ i ] [ SCRIT ] ) ; }
} e l s e {
i f ( i ! = 0 ) {
c l o s e ( P f d s [ i ] [ SCRIT ] ) ; }
} }
f d=open (F ,O RDONLY ) ; i f ( fd <0) {
#i f d e f DEBUG
z p r i n t f ( 2 , ” I m p o s s i b i l e a p r i r e i l f i l e %s \n” ,F ) ;
#endif
return ( − 1 ) ; }
/∗ i l f i l e d e v e e s s e r e l e t t o p e r l i n e e ∗/
linenum =1; /∗ prima l i n e a ∗/
r e t v a l =0; /∗ l i n e e c h e s o d d i s f a n o =0 ∗/
f l a g =0;
/∗ s i n c r o n i z z a z i o n e ’ e s t e s a ’ i n g r a d o d i a s s i c u r a r c i l ’ a l t e r n a n z a d e l l e
∗ i n f o r m a z i o n i anche i n s e g u i t o a l l a t e r m i n a z i o n e d i uno o p i u ’ f i g l i
∗ s i usa una v a r i a b i l e p e r memorizzare l ’ i n d i c e d e l l a p i p e da c u i
∗ a t t e n d e r e l ’ ok . Se l a r e a d da t a l e i n d i c e r e s t i t u i s c e 0 −> a l l o r a i l
∗ f i g l i o r e l a t i v o e ’ t e r m i n a t o e b i s o g n a ’ a g g a n c i a r s i ’ a l p r e c e d e n t e .
∗ Nel c a s o e s t r e m o i n c u i un s o l o p r o c e s s o f i g l i o rimanga i n e s s e r e ,
∗ l a p i p e d i l e t t u r a e q u e l l a d i s c r i t t u r a vanno a c o i n c i d e r e
∗ s b l o c c a n d o c o n t i n u a m e n t e l ’ o u t p u t d i t a l e p r o c e s s o ∗/
p i p e d i s i n c = i n d i c e ; /∗ i n i z i a m o con q u e l l a ’ c a n o n i c a ’ ∗/
f o r ( ; ; ) {
nr=r e a d ( fd ,& ch , 1 ) ; i f ( nr==0) {
return ( r e t v a l ) ; }
i f ( nr <0) { /∗ e r r o r e ∗/
#i f d e f DEBUG
z p r i n t f ( 2 , ” I m p o s s i b i l e l e g g e r e d a l f i l e %s \n” ,F ) ;
#endif
return ( − 1 ) ; }
/∗ c a r a t t e r e l e t t o , c o n t r o l l o s e f i n e l i n e a ∗/
i f ( ch== ’ \n ’ ) { linenum++;
f l a g =0;
}
/∗ d a l t e s t o : s e t r o v o i l c a r a t t e r e a s s e g n a t o C[ i n d i c e ] , d e v o r i p o r t a r e
∗ i l numero d i l i n e a su s t d o u t . Se i l c a r a t t e r e s i t r o v a p i u ’
∗ v o l t e n e l l a s t e s s a l i n e a devo r i p o r t a r e i l numero s o l o
∗ una v o l t a , q u i n d i uso un f l a g che c o n t r o l l o a f i n e l i n e a ∗/
i f ( ( ch==C [ i n d i c e ])&& f l a g ==0) { f l a g =1;
r e t v a l ++; /∗ i n c r e m e n t o c o n t a t o r e ∗/
/∗ a g g i u n g o s i n c r o n i z z a z i o n e , a t t e n d o c a r a t t e r e da p i p e
∗ con i n d i c e p i p e d i s i n c e g e s t i s c o l ’ e v e n t u a l e
∗ t e r m i n a z i o n e d e l f i g l i o a s s o c i a t o ∗/
f o r ( ; ; ) {
nrp=r e a d ( P f d s [ p i p e d i s i n c ] [ LETT] , &dummy , 1 ) ; i f ( nrp==0) {
/∗ p i p e c h i u s a , a g g a n c i a m o c i a l f i g l i o p r e c e d e n t e ∗/
i f ( p i p e d i s i n c >0) { p i p e d i s i n c −−;
} e l s e {
p i p e d i s i n c=Npipe −1;
}
continue ; }
i f ( nrp==−1) {
/∗ e r r o r e , s e g n a l a r e ∗/
#i f d e f DEBUG
z p r i n t f ( 2 , ” E r r o r e p i p e d i s i n c r o n i z z a z i o n e \n” ) ;
#endif
return ( − 1 ) ; }
break ; }
/∗ s e sono q u i p o s s o s c r i v e r e ∗/
z p r i n t f ( 1 , ” L i n e a %d c o n t i e n e %c \n” , linenum , C [ i n d i c e ] ) ; /∗ o r a do i l v i a a l f i g l i o s u c c e s s i v o : l ’ i n d i c e d e l l a p i p e
∗ i n c u i s c r i v e r e e ’ i n d i c e +1 a meno che no s i t r a t t i d e l l ’ u l t i m o
∗ f i g l i o ( q u e l l o con i n d i c e =( N f i g l i −1)) che d e v e s c r i v e r e s u l l a
∗ p i p e d i i n d i c e 0 ∗/
i f ( i n d i c e != N f i g l i −1) {
w r i t e ( P f d s [ i n d i c e + 1 ] [ SCRIT] , &dummy , 1 ) ; } e l s e {
w r i t e ( P f d s [ 0 ] [ SCRIT] , &dummy , 1 ) ; }
}
}
/∗ mai q u i ! ∗/
return ( − 1 ) ; }
void z p r i n t f ( i n t fd , const char ∗ fmt , . . . ) { /∗ p r i n t f wrapper u s i n g w r i t e i n s t e a d ∗/
s t a t i c char msg [ 2 5 6 ] ; v a l i s t ap ;
i n t n ;
v a s t a r t ( ap , fmt ) ;
n=v s n p r i n t f ( msg , 2 5 6 , fmt , ap ) ; w r i t e ( fd , msg , n ) ;
v a e n d ( ap ) ; }
3. Invertire l’ordine di sincronizzazione dei figli nell’esercizio es102.c (es103.c) Soluzione:
F[N−1]
Parent
F[0] F[1] F[N−1]
N wait()
pipes[N−1]
pipes[2]
pipes[N−1]
pipes[1] pipes[2]
pipes[0]
F[1]
F[1]
pipes[1]
pipes[1]
/∗ f i l e : e s 1 0 3 . c
∗ j o b : i n v e r s i o n e d ’ o r d i n e su e s 1 0 2 . c
∗/
#include <s t d i o . h>
#include < s t d l i b . h>
#include <u n i s t d . h>
#include <s y s / t y p e s . h>
#include <s y s / w a i t . h>
#include <s y s / s t a t . h>
#include < f c n t l . h>
#include <s t d a r g . h>
typedef i n t p i p e t [ 2 ] ; /∗ t i p o p e r p i p e ∗/
#define SCRIT 1
#define LETT 0
char ∗F ; /∗ Nome d e l f i l e , v a r i a b i l e g l o b a l e ∗/
i n t N; /∗ Numero d i c a r a t t e r i ∗/
char ∗C ; /∗ E l e n c o d e i c a r a t t e r i , a l l o c a z i o n e d i n a m i c a ∗/
i n t Npipe ; /∗ Numero d i p i p e da c r e a r e ∗/
p i p e t ∗ P f d s ; /∗ Array d i p i p e , a l l o c a z i o n e d i n a m i c a ∗/
i n t N f i g l i ; /∗ Numero d i f i g l i da f o r k a r e ∗/
i n t ∗ P i d s ; /∗ Array d i p i d , a l l o c a z i o n e d i n a m i c a ∗/
/∗ a b b i n a m e n t o s n p r i n t f+w r i t e ∗/
void z p r i n t f ( i n t fd , const char ∗ fmt , . . . ) ; /∗ f u n z i o n e f i g l i o ∗/
i n t f i g l i o ( i n t ) ;
char ok= ’Q ’ ; /∗ c a r a t t e r e ( c a s u a l e ) c h e i n v i a m o s u l l a p i p e p e r l a s i n c r o n i z z a z i o n e ∗/
i n t main ( i n t a r g c , char ∗∗ argv , char ∗∗ envp ) { i n t i , j ; /∗ q u a l c h e c o n t a t o r e ∗/
/∗ D e t e r m i n a z i o n e d e i d a t i d a l l a command l i n e ∗/
switch ( a r g c ) { case 0 : case 1 : case 2 :
z p r i n t f ( 2 , ” I n s e r i r e i l nome d i f i l e ed almeno un c a r a t t e r e \n” ) ; return ( 1 ) ;
}
F = a r g v [ 1 ] ;
N = a r g c −2; /∗ a r g c v a l e 1 s e non c i sono a r g o m e n t i ∗/
C = m a l l o c (N∗ s i z e o f ( char ) ) ; i f (C==NULL) {
z p r i n t f ( 2 , ” I m p o s s i b i l e a l l o c a r e C\n” ) ; return ( 1 ) ;
}
f o r ( i =0; i <N; i ++) {
C [ i ]= a r g v [ i + 2 ] [ 0 ] ; /∗ p r e n d o i l primo c a r a t t e r e d e l l a s t r i n g a a r g v [ i +2] ∗/
}
#i f d e f DEBUG
z p r i n t f ( 1 , ”Nome d e l f i l e : %s \n” ,F ) ; z p r i n t f ( 1 , ”Numero d i c a r a t t e r i %d\n” ,N ) ; f o r ( i =0; i <N; i ++) {
z p r i n t f ( 1 , ” C a r a t t e r e d i i n d i c e %d = %c \n” , i , C [ i ] ) ; }
#endif
/∗ P r e d i s p o s i z i o n e d e l s i s t e m a d i s i n c r o n i z z a z i o n e
∗ f r a i p r o c e s s i f i g l i : s i u t i l i z z a una p i p e p e r
∗ c o l l e g a r e o g n i f i g l i o a l s u c c e s s i v o ; l a s i n c r o n i z z a z i o n e
∗ d e l f i g l i o d i i n d i c e ’ k ’ s i o t t i e n e a t t e n d e n d o un
∗ c a r a t t e r e d a l l a p i p e che l o c o l l e g a a l f i g l i o d i
∗ i n d i c e ’ k −1 ’. ∗/
Npipe = N; /∗ una p i p e i n u s c i t a da o g n i f i g l i o ∗/
P f d s = m a l l o c ( Npipe ∗ s i z e o f ( p i p e t ) ) ; i f ( P f d s==NULL) {
z p r i n t f ( 2 , ” I m p o s s i b i l e a l l o c a r e P f d s \n” ) ; return ( 1 ) ;
}
f o r ( i =0; i <Npipe ; i ++) { i f ( p i p e ( P f d s [ i ] ) ! = 0 ) {
z p r i n t f ( 2 , ” I m p o s s i b i l e c r e a r e l a p i p e %d\n” , i ) ; return ( 1 ) ;
} }
/∗ C r e a z i o n e p r o c e s s i f i g l i :
∗ d a l t e s t o , b i s o g n a c r e a r e un p r o c e s s o f i g l i o p e r o g n i c a r a t t e r e
∗ q u i n d i N f i g l i=N
∗ V i s t o che i l p a d r e d e v e stampare i v a l o r i d i u s c i t a d e i p r o c e s s i
∗ f i g l i , s i devono memorizzare i p i d i n o r d i n e d i i n d i c e p e r p o i
∗ a b b i n a r e i r i s u l t a t i d e l l e w a i t . L ’ a r r a y d i p i d d e v e e s s e r e
∗ a l l o c a t o dinamicamente ∗/
N f i g l i = N;
P i d s=m a l l o c ( N f i g l i ∗ s i z e o f ( i n t ) ) ; i f ( P i d s==NULL) {
z p r i n t f ( 2 , ” I m p o s s i b i l e a l l o c a r e P i d s \n” ) ; return ( 1 ) ;
}
f o r ( i =0; i <N f i g l i ; i ++) { P i d s [ i ]= f o r k ( ) ;
switch ( P i d s [ i ] ) {
case 0 : /∗ f i g l i o d i i n d i c e i ∗/
return ( f i g l i o ( i ) ) ; /∗ chiamo f u n z i o n e f i g l i o e uso v a l o r e d i r i t o r n o come e x i t d e l p r o c e s s o ∗/
case −1:
z p r i n t f ( 2 , ” I m p o s s i b i l e f o r k a r e i l p r o c e s s o %d\n” , i ) ; return ( 1 ) ;
break ; }
#i f d e f DEBUG
/∗ s o l o i l p r o c e s s o p a d r e e s e g u e q u e s t e l i n e e ∗/
z p r i n t f ( 1 , ” F o r k a t o p r o c e s s o %d p e r i n d i c e %d\n” , P i d s [ i ] , i ) ;
#endif }
/∗ I l p a d r e non u t i l i z z a n e s s u n a p i p e i n quando l a s i n c r o n i z z a z i o n e
∗ v i e n e f a t t a t o t a l m e n t e f r a i f i g l i . E v e n t u a l m e n t e (ma c i sono
∗ anche a l t r i modi ) i l p a d r e puo ’ d a r e i l v i a a l primo f i g l i o .
∗ U t i l i z z i a m o q u e s t a p o s s i b i l i t a ’ ed u t i l i z z i a m o un s i n g o l o
∗ c a r a t t e r e memorizzato i n ok p e r l ’ i n v i o ∗/
i f ( w r i t e ( P f d s [ 0 ] [ SCRIT] , & ok , 1 ) ! = 1 ) { /∗ c o n t r o l l o d i s c r i t t u r a a v v e n u t a ∗/
z p r i n t f ( 2 , ” I m p o s s i b i l e i n v i a r e su %d\n” , P f d s [ 0 ] [ SCRIT ] ) ; return ( 1 ) ;
}
/∗ o r a c h i u d i a m o t u t t e l e p i p e i n u t i l i z z a t e d a l padre , compresa
∗ q u e l l a i n c u i abbiamo appena s c r i t t o ( i l c a r a t t e r e rimane ! ) ∗/
f o r ( i =0; i <Npipe ; i ++) { c l o s e ( P f d s [ i ] [ SCRIT ] ) ; c l o s e ( P f d s [ i ] [ LETT ] ) ; }
/∗ Recupero d e l l e i n f o r m a z i o n i d a i p r o c e s s i f i g l i t r a m i t e l a w a i t ∗/
f o r ( i =0; i <N f i g l i ; i ++) { i n t p i d x ;
i n t s t a t u s ;
p i d x = w a i t (& s t a t u s ) ;
/∗ a b b i n a m e n t o d e l l e i n f o r m a z i o n i a l l ’ i n d i c e d e l f i g l i o ∗/
f o r ( j =0; j <N f i g l i ; j ++) { i f ( p i d x==P i d s [ j ] ) {
i f (WEXITSTATUS( s t a t u s )==255) {
/∗ c o n v e n z i o n e : s e g n a l a z i o n e d ’ e r r o r e ∗/
z p r i n t f ( 1 ,
” I l f i g l i o c h e c e r c a i l c a r a t t e r e %c ha i n c o n t r a t o un e r r o r e \n” , C [ j ] ) ;
} e l s e {
z p r i n t f ( 1 ,
” I l f i g l i o c h e c e r c a i l c a r a t t e r e %c ha t r o v a t o %d l i n e e \n” , C [ j ] ,WEXITSTATUS( s t a t u s ) ) ;
} } } }
return ( 0 ) ; }
/∗ F un z io n e f i g l i o ∗/
i n t f i g l i o ( i n t i n d i c e ) {
/∗ Ogni f i g l i o d e v e c e r c a r e l e o c c o r r e n z e d i C[ i ] n e l f i l e F ,
∗ q u i n d i i l f i l e NON d e v e e s s e r e c o n d i v i s o ma a p e r t o i n d i p e n d e n t e m e n t e
∗ da o g n i f i g l i o ∗/
i n t f d ;
i n t linenum ; /∗ c o n t a t o r e d i l i n e a c o r r e n t e ∗/
char ch ; /∗ c a r a t t e r e d i a p p o g g i o ∗/
i n t r e t v a l ; /∗ v a l o r e d i r i t o r n o ∗/
i n t nr ; /∗ numero d i c a r a t t e r i l e t t i d a l l a r e a d ∗/
i n t f l a g ; /∗ s e 0 c a r a t t e r e non t r o v a t o , s e 1 t r o v a t o ∗/
i n t nrp ; /∗ numero d i c a r l e t t i da r e a d su p i p e ∗/
char dummy ; /∗ c a r a t t e r e d i a p p o g g i o p e r l e t t / s c r i t t p i p e ∗/
i n t i ; /∗ un c o n t a t o r e ∗/
i n t p i p e d i s i n c ; /∗ i n d i c e d e l l a p i p e d i s i n c r o n i z z a z i o n e da c u i f a r e l a r e a d ∗/
/∗ C h i u s u r a d e i l a t i d e l l e p i p e p e r e v i t a r e i l d e a d l o c k quando
∗ un f i g l i o t e r m i n a prima d e g l i a l t r i e non puo ’ p r o s e g u i r e
∗ n e l l ’ a t t i v i t a ’ d i s i n c r o n i z z a z i o n e . Se almeno i l a t i
∗ d i s c r i t t u r a sono p o s s e d u t i ognuno da un s o l o p r o c e s s o
∗ l a t e r m i n a z i o n e d i q u e s t o p r o v o c a un comportamento non
∗ b l o c c a n t e p e r l a r e a d ∗/
f o r ( i =0; i <Npipe ; i ++) {
/∗ c h i u d o i l a t i d i s c r i t t u r a s e non e ’ l a p i p e
∗ che usa q u e s t o f i g l i o ∗/
i f ( i ! = ( i n d i c e ) ) {
c l o s e ( P f d s [ i ] [ SCRIT ] ) ; }
}
f d=open (F ,O RDONLY ) ; i f ( fd <0) {
#i f d e f DEBUG
z p r i n t f ( 2 , ” I m p o s s i b i l e a p r i r e i l f i l e %s \n” ,F ) ;
#endif
return ( − 1 ) ; }
/∗ i l f i l e d e v e e s s e r e l e t t o p e r l i n e e ∗/
linenum =1; /∗ prima l i n e a ∗/
r e t v a l =0; /∗ l i n e e c h e s o d d i s f a n o =0 ∗/
f l a g =0;
/∗ s i n c r o n i z z a z i o n e ’ e s t e s a ’ i n g r a d o d i a s s i c u r a r c i l ’ a l t e r n a n z a d e l l e
∗ i n f o r m a z i o n i anche i n s e g u i t o a l l a t e r m i n a z i o n e d i uno o p i u ’ f i g l i
∗ s i usa una v a r i a b i l e p e r memorizzare l ’ i n d i c e d e l l a p i p e da c u i
∗ a t t e n d e r e l ’ ok . Se l a r e a d da t a l e i n d i c e r e s t i t u i s c e 0 −> a l l o r a i l
∗ f i g l i o r e l a t i v o e ’ t e r m i n a t o e b i s o g n a ’ a g g a n c i a r s i ’ a l p r e c e d e n t e .
∗ Nel c a s o e s t r e m o i n c u i un s o l o p r o c e s s o f i g l i o rimanga i n e s s e r e ,
∗ l a p i p e d i l e t t u r a e q u e l l a d i s c r i t t u r a vanno a c o i n c i d e r e
∗ s b l o c c a n d o c o n t i n u a m e n t e l ’ o u t p u t d i t a l e p r o c e s s o ∗/
p i p e d i s i n c = ( i n d i c e +1)%Npipe ; /∗ i n i z i a m o con q u e l l a ’ c a n o n i c a ’ ∗/
f o r ( ; ; ) {
nr=r e a d ( fd ,& ch , 1 ) ; i f ( nr==0) {
return ( r e t v a l ) ; }
i f ( nr <0) { /∗ e r r o r e ∗/
#i f d e f DEBUG
z p r i n t f ( 2 , ” I m p o s s i b i l e l e g g e r e d a l f i l e %s \n” ,F ) ;
#endif
return ( − 1 ) ; }
/∗ c a r a t t e r e l e t t o , c o n t r o l l o s e f i n e l i n e a ∗/
i f ( ch== ’ \n ’ ) { linenum++;
f l a g =0;
}
/∗ d a l t e s t o : s e t r o v o i l c a r a t t e r e a s s e g n a t o C[ i n d i c e ] , d e v o r i p o r t a r e
∗ i l numero d i l i n e a su s t d o u t . Se i l c a r a t t e r e s i t r o v a p i u ’
∗ v o l t e n e l l a s t e s s a l i n e a devo r i p o r t a r e i l numero s o l o
∗ una v o l t a , q u i n d i uso un f l a g che c o n t r o l l o a f i n e l i n e a ∗/
i f ( ( ch==C [ i n d i c e ])&& f l a g ==0) { f l a g =1;
r e t v a l ++; /∗ i n c r e m e n t o c o n t a t o r e ∗/
/∗ a g g i u n g o s i n c r o n i z z a z i o n e , a t t e n d o c a r a t t e r e da p i p e
∗ con i n d i c e p i p e d i s i n c e g e s t i s c o l ’ e v e n t u a l e
∗ t e r m i n a z i o n e d e l f i g l i o a s s o c i a t o ∗/
f o r ( ; ; ) {
nrp=r e a d ( P f d s [ p i p e d i s i n c ] [ LETT] , &dummy , 1 ) ; i f ( nrp==0) {
/∗ p i p e c h i u s a , a g g a n c i a m o c i a l f i g l i o s u c c e s s i v o ∗/
i f ( p i p e d i s i n c <(Npipe −1)) { p i p e d i s i n c ++;
} e l s e {
p i p e d i s i n c =0;
}
continue ; }
i f ( nrp==−1) {
/∗ e r r o r e , s e g n a l a r e ∗/
#i f d e f DEBUG
z p r i n t f ( 2 , ” E r r o r e p i p e d i s i n c r o n i z z a z i o n e \n” ) ;
#endif
return ( − 1 ) ; }
break ; }
/∗ s e sono q u i p o s s o s c r i v e r e ∗/
z p r i n t f ( 1 , ” L i n e a %d c o n t i e n e %c \n” , linenum , C [ i n d i c e ] ) ; /∗ o r a do i l v i a a l f i g l i o c h e d e v e e s e g u i r e l ’ o p e r a z i o n e
∗ dopo q u e l l o c o r r e n t e , o v v e r o i l f i g l i o a v e n t e i n d i c e minore
∗ d i 1 ( o l ’ u l t i m o n e l c a s o d e l f i g l i o con i n d i c e ==0):
∗ l ’ i n d i c e d e l l a p i p e i n c u i s c r i v e r e e ’ u g u a l e a l l ’ i n d i c e
∗ d e l f i g l i o ∗/
w r i t e ( P f d s [ i n d i c e ] [ SCRIT] , &dummy , 1 ) ; }
}
/∗ mai q u i ! ∗/
return ( − 1 ) ; }
void z p r i n t f ( i n t fd , const char ∗ fmt , . . . ) { /∗ p r i n t f wrapper u s i n g w r i t e i n s t e a d ∗/
s t a t i c char msg [ 2 5 6 ] ; v a l i s t ap ;
i n t n ;
v a s t a r t ( ap , fmt ) ;
n=v s n p r i n t f ( msg , 2 5 6 , fmt , ap ) ; w r i t e ( fd , msg , n ) ;
v a e n d ( ap ) ; }
4. Creiamo un sorgente C es104.c che possa servire come base di partenza per la realizzazione di appli- cazioni concorrenti.
Soluzione:
/∗ Esempio d i b a s e comune ∗/
#include <s t d i o . h>
#include <u n i s t d . h>
#include < s t d l i b . h>
#include <s y s / w a i t . h>
#include <s t d a r g . h>
/∗ Numero d i p i p e da c r e a r e ∗/
i n t n p i p e ;
/∗ Numero d i p r o c e s s i f i g l i ∗/
i n t n f i g l i ;
/∗ t i p o d i d a t o p e r c o n t e n e r e i f i l e d e s c r i p t o r s
∗ d i una p i p e ∗/
typedef i n t p i p e t [ 2 ] ;
/∗ c o n t e n i t o r e p e r i f i l e d e s c r i p t o r s d i t u t t e
∗ l e p i p e u t i l i z z a t e ∗/
p i p e t ∗ p i p e f d s ;
/∗ p r o t o t i p o f u n z i o n e p r o c e s s o f i g l i o , da p e r s o n a l i z z a r e ∗/
i n t f i g l i o ( i n t a r g ) ; /∗ p r o t o t i p o z p r i n t f ∗/
void z p r i n t f ( i n t fd , const char ∗ fmt , . . . ) ; i n t main ( i n t a r g c , char ∗∗ a r g v ) {
i n t p i d f ; i n t s t a t u s ; i n t i ; n p i p e =1;
n f i g l i =1;
/∗ a l l o c a z i o n e memoria d i n a m i c a p e r p i p e f d s ∗/
p i p e f d s=m a l l o c ( n p i p e ∗ s i z e o f ( p i p e t ) ) ; i f ( p i p e f d s ==0) {
p r i n t f ( ” E r r o r e \n” ) ; return ( 1 ) ;
}
/∗ c r e a z i o n e d e l l e p i p e ∗/
f o r ( i =0; i <n p i p e ; i ++) { i f ( p i p e ( p i p e f d s [ i ] ) ! = 0 ) {
p r i n t f ( ” E r r o r e \n” ) ; return ( 1 ) ;
} }
/∗ c r e a z i o n e d e i p r o c e s s i f i g l i ∗/
f o r ( i =0; i < n f i g l i ; i ++) { switch ( f o r k ( ) ) {
case 0 :
/∗ i n v o c a z i o n e d e l l a f u n z i o n e f i g l i o
∗ e t e r m i n a z i o n e d e l p r o c e s s o con
∗ e x i t v a l u e u g u a l e a l r e t u r n v a l u e
∗ d e l l a f u n z i o n e f i g l i o ( ) ∗/
return ( f i g l i o ( i ) ) ; case −1:
p r i n t f ( ” E r r o r e \n” ) ; return ( 1 ) ;
d e f a u l t :
/∗ s o l o d a l p a d r e ∗/
; }
}
/∗ c i c l o e s e g u i t o d a l s o l o p r o c e s s o p a d r e
∗ p e r r e c u p e r a r e l e i n f o d i t e r m i n a z i o n e
∗ d e i p r o c e s s i f i g l i ∗/
f o r ( i =0; i < n f i g l i ; i ++) {
p i d f=w a i t (& s t a t u s ) ; }
/∗ e x i t v a l u e d e l p r o c e s s o p a d r e ∗/
return ( 0 ) ; }
/∗ f u n z i o n e p r o c e s s o f i g l i o , d e f i n i z i o n e ∗/
i n t f i g l i o ( i n t a r g ) { return ( 0 ) ;
}
/∗ a b b i n a m e n t o s n p r i n t f+w r i t e ∗/
void z p r i n t f ( i n t fd , const char ∗ fmt , . . . ) { s t a t i c char msg [ 2 5 6 ] ;
v a l i s t ap ; i n t n ;
v a s t a r t ( ap , fmt ) ;
n=v s n p r i n t f ( msg , 2 5 6 , fmt , ap ) ; w r i t e ( fd , msg , n ) ;
v a e n d ( ap ) ; }
5. Creiamo un Makefile per la compilazione dell’esempio Soluzione:
e s e r c i z i o : e s 1 0 4 . c
g c c −Wall −o e s e r c i z i o e s 1 0 4 . c