• Non ci sono risultati.

Lab. di Sistemi Operativi Esercitazioni proposte per la lezione del 6 maggio 2011

N/A
N/A
Protected

Academic year: 2021

Condividi "Lab. di Sistemi Operativi Esercitazioni proposte per la lezione del 6 maggio 2011"

Copied!
21
0
0

Testo completo

(1)

Lab. di Sistemi Operativi

Esercitazioni proposte per la lezione del 6 maggio 2011

Utilizzando il compilatore gcc in Linux e disponendosi in gruppi di due persone per ogni PC del labora- torio.

1. Utilizzo della funzione write. Creare un sorgente in linguaggio c (es81.c) che riversi su stdout la stringa costante ”Ciao, mondo!”.

2. Modificare es81.c in modo che i caratteri siano scritti su stderr. Verificare il comportamento del programma cos`ı modificato utilizzando la ridirezione della shell.

3. isualizzare la man page di write. Attenzione: esistono differenti man page per write, visualizzare quella nella sezione di nostro interesse (2, syscall).

4. Modificare es81.c in modo che il valore ritornato da write venga reso disponibile come exit value del processo.

5. Modificare es81.c in modo che il file descriptor venga assegnato dal primo argomento della linea di comando, o venga imposto pari a 1 se assente. Cosa avviene se si indica un fd diverso da 1 o 2?

6. Modificare es81.c in modo che la stringa scritta contenga il valore numerico di fd. Utilizzare un array di char e popolarlo con sprintf.

7. Differenze fra printf e write. Modificare es81.c in modo che l’emissione del carattere di fine linea avvenga con quache secondo di ritardo ed osservare il risultato. Provare lo stesso con la printf.

8. (15 minuti) es82.c Creazione di file. Si utilizzi la funzione open() in un sorgente c il cui obiettivo sia quello di creare un file nella directory corrente avente per nome la stringa rappresentata dal primo argomento.

9. Modifichiamo es82.c in modo da recuperare il valore di ritorno della open ed utilizzarlo come file descriptor per una write.

10. Chiusura di un file: la funzione close. Modificare es82.c in modo che il file creato sia chiuso prima della terminazione.

11. (15 minuti) es83.c Utilizzo di un file esistente. Progettare un programma c che apra il file indicato dal primo argomento e sovrascriva i primi 4 caratteri con la stringa ”ciao”

12. Cosa succede se il file vittima `e pi`u lungo di 4 caratteri? E se fosse pi`u corto?

13. Modificare es83.c in modo che il file venga troncato alla dimensione 4.

14. (25 minuti) es84.c Lettura da file. Creare un sorgente c che legga i primi N caratteri (N<100) dal file F con N ed F rispettivamente primo e secondo argomento della command line.

15. (15 minuti) Modificare es84.c in modo che gli N caratteri letti siano copiati nello stesso file a partire dalla posizione K, con K terzo argomento.

16. Utilizzando la funzione fork() creare un nuovo processo (es85.c)

17. Presentare su stdout il valore ritornato dalla fork(). Si utilizzi la coppia snprintf()/write() al posto della semplice printf()

18. Per quale motivo troviamo su stdout due messaggi (con valori differenti)?

19. Verificare il ruolo di padre e figlio visualizzandolo su standard output.

(2)

20. La funzione fork() restituisce -1 in caso di errore (e, ovviamente, non genera il nuovo processo). Ag- giungere questa verifica associandola ad un opportuno messaggio d’errore.

21. Sia il processo padre che il processo figlio hanno un proprio exit value. Utilizzare la funzione wait() per recuperare l’exit value del processo figlio.

22. La wait svolge anche un ruolo di sincronizzazione fra processo padre e processo figlio?

23. (25 minuti) es86.c Condivisione di file. Si progetti una applicazione concorrente composta da due processi, padre e figlio, tali che il file rappresentato dal primo argomento sia aperto prima della fork() ed utilizzato in lettura in modo condiviso per contare i caratteri contenuti leggendoli ad uno ad uno.

24. Creare un Makefile per la compilazione di es86.

25. (10 minuti) es87.c Comportamento della printf in applicazioni concorrenti. Creare un sorgente che utilizzi la printf per emettere una stringa priva di fine linea prima della fork().

26. L’esecuzione di es87 riporta la stringa iniziale per due volte su stdout. Proviamo a modificare il sorgente introducendo la write al posto della printf.

27. (15 minuti) es88.c Creazione di pi`u processi. Creare un sorgente che generi un numero di figli uguale al numero passato come primo argomento.

28. (10 minuti) es88.c Modificare es88.c in modo che ogni figlio stampi su stdout il proprio indice.

29. (15 minuti) es88.c Recupero degli exit value dei processi figli: modificare es88.c in modo che il processo padre attenda la terminazione di tutti i processi figli riportando su stdout gli exit value di ogni processo accanto al pid del processo terminato.

30. Un po’ di ordine: modifichiamo es88.c in modo che le operazioni delegate ai processi figli siano incluse in una funzione.

(3)

Soluzione

Esercitazioni proposte per la lezione del 6 maggio 2011

Utilizzando il compilatore gcc in Linux e disponendosi in gruppi di due persone per ogni PC del labora- torio.

1. Utilizzo della funzione write. Creare un sorgente in linguaggio c (es81.c) che riversi su stdout la stringa costante ”Ciao, mondo!”.

Soluzione:

/∗ f i l e : e s 8 1 . c

∗ j o b : s c r i t t u r a su s t d o u t con w r i t e

∗/

#include <u n i s t d . h>

i n t main ( i n t a r g c , char ∗∗ a r g v ) { w r i t e ( 1 , ” Ciao , mondo ! \ n” , 1 3 ) ; return ( 0 ) ;

}

2. Modificare es81.c in modo che i caratteri siano scritti su stderr. Verificare il comportamento del programma cos`ı modificato utilizzando la ridirezione della shell.

Soluzione:

/∗ f i l e : e s 8 1 . c

∗ j o b : s c r i t t u r a su s t d o u t con w r i t e

∗/

#include <u n i s t d . h>

i n t main ( i n t a r g c , char ∗∗ a r g v ) { w r i t e ( 2 , ” Ciao , mondo ! \ n” , 1 3 ) ; return ( 0 ) ;

}

/∗ $ . / e s 8 1 > / d e v / n u l l

∗ $ Ciao , mondo !

∗ $ . / e s 8 1 2> / dev / n u l l

∗ $

∗/

3. isualizzare la man page di write. Attenzione: esistono differenti man page per write, visualizzare quella nella sezione di nostro interesse (2, syscall).

Soluzione:

$ man 2 write

4. Modificare es81.c in modo che il valore ritornato da write venga reso disponibile come exit value del processo.

Soluzione:

/∗ f i l e : e s 8 1 . c

∗ j o b : s c r i t t u r a su s t d o u t con w r i t e

∗/

#include <u n i s t d . h>

(4)

i n t main ( i n t a r g c , char ∗∗ a r g v ) {

/∗ l ’ e x i t v a l u e d e l p r o c e s s o c o i n c i d e

∗ con i l v a l o r e d i r i t o r n o d e l l a w r i t e

∗ o v v e r o con i l numero d i c a r a t t e r i

∗ e f f e t t i v a m e n t e s c r i t t i . ∗/

return ( w r i t e ( 2 , ” Ciao , mondo ! \ n” , 1 3 ) ) ; }

5. Modificare es81.c in modo che il file descriptor venga assegnato dal primo argomento della linea di comando, o venga imposto pari a 1 se assente. Cosa avviene se si indica un fd diverso da 1 o 2?

Soluzione:

/∗ f i l e : e s 8 1 . c

∗ j o b : s c r i t t u r a su s t d o u t con w r i t e

∗/

#include <u n i s t d . h>

#include < s t d l i b . h>

i n t main ( i n t a r g c , char ∗∗ a r g v ) { i n t f d ;

i f ( a r g c <2) {

/∗ n e s s u n argomento ∗/

f d =1;

} e l s e {

/∗ f d i n a r g v [ 1 ] , numero ∗/

f d=a t o i ( a r g v [ 1 ] ) ; }

return ( w r i t e ( fd , ” Ciao , mondo ! \ n” , 1 3 ) ) ; }

6. Modificare es81.c in modo che la stringa scritta contenga il valore numerico di fd. Utilizzare un array di char e popolarlo con sprintf.

Soluzione:

/∗ f i l e : e s 8 1 . c

∗ j o b : s c r i t t u r a su s t d o u t con w r i t e

∗/

#include <u n i s t d . h>

#include < s t d l i b . h>

#include <s t d i o . h>

#include < s t r i n g . h>

char s t r i n g a [ 2 5 6 ] ;

i n t main ( i n t a r g c , char ∗∗ a r g v ) { i n t f d ;

i f ( a r g c <2) { f d =1;

} e l s e {

f d=a t o i ( a r g v [ 1 ] ) ; }

s n p r i n t f ( s t r i n g a , 2 5 6 , ” f d=%d : Ciao , mondo ! \ n” , f d ) ; return ( w r i t e ( fd , s t r i n g a , s t r l e n ( s t r i n g a ) ) ) ;

}

(5)

7. Differenze fra printf e write. Modificare es81.c in modo che l’emissione del carattere di fine linea avvenga con quache secondo di ritardo ed osservare il risultato. Provare lo stesso con la printf.

Soluzione:

/∗ f i l e : e s 8 1 . c

∗ j o b : w r i t e e p r i n t f , un po ’ d i p r o v e

∗/

#include <u n i s t d . h>

#include < s t d l i b . h>

#include <s t d i o . h>

#include < s t r i n g . h>

char s t r i n g a [ 2 5 6 ] ;

i n t main ( i n t a r g c , char ∗∗ a r g v ) { i n t f d ;

i f ( a r g c <2) { f d =1;

} e l s e {

f d=a t o i ( a r g v [ 1 ] ) ; }

/∗ r i m o s s o i l f i n e l i n e a ’ \ n ’ ∗/

s n p r i n t f ( s t r i n g a , 2 5 6 , ” f d=%d : Ciao , mondo ! ” , f d ) ; w r i t e ( fd , s t r i n g a , s t r l e n ( s t r i n g a ) ) ;

s l e e p ( 1 0 ) ; /∗ a t t e n d o 10 s e c o n d i ∗/

w r i t e ( fd , ” \n” , 1 ) ;

s l e e p ( 1 0 ) ; /∗ a t t e n d o 10 s e c o n d i ∗/

/∗ o r a abbiamo v e r i f i c a t o c h e l a w r i t e non ha r i t a r d i ∗/

/∗ vediamo con l a p r i n t f ∗/

w r i t e ( fd , ” i n v o c o l a p r i n t f : ” , 1 8 ) ; p r i n t f ( ” f d=%d : Ciao , mondo ! ” , f d ) ;

s l e e p ( 1 0 ) ; /∗ a t t e n d o a l t r i 10 s e c o n d i ∗/

p r i n t f ( ” \n” ) ; /∗ s o l o ora , dopo i 10 s e c o n d i , l a p r i n t f mostra i l suo e f f e t t o : i c a r a t t e r i d e l l a prima p r i n t f sono s t a t i r i t a r d a t i f i n o a l \n

∗/

return ( 0 ) ; }

8. (15 minuti) es82.c Creazione di file. Si utilizzi la funzione open() in un sorgente c il cui obiettivo sia quello di creare un file nella directory corrente avente per nome la stringa rappresentata dal primo argomento.

Soluzione:

/∗ f i l e : e s 8 2 . c

∗ j o b : open

∗/

#include <u n i s t d . h>

#include < s t d l i b . h>

#include <s y s / t y p e s . h>

#include <s y s / s t a t . h>

#include < f c n t l . h>

i n t main ( i n t a r g c , char ∗∗ a r g v ) {

(6)

i f ( a r g c <2) {

/∗ manca i l nome , usciamo ∗/

w r i t e ( 2 , ” I n s e r i r e i l nome d e l f i l e ! \ n” , 2 8 ) ; e x i t ( 1 ) ;

} e l s e {

open ( a r g v [ 1 ] ,O WRONLY| O CREAT | O EXCL, 0 0 6 6 6 ) ; /∗ a t t e n z i o n e : l a c o s t a n t e o t t a l e 0 0 6 6 6 ,

∗ r e l a t i v a a i p e r m e s s i , v i e n e a p p l i c a t a

∗ a l f i l e dopo l a m a s c h e r a t u r a ad o p e r a

∗ d i umask ∗/

}

return ( 0 ) ; }

9. Modifichiamo es82.c in modo da recuperare il valore di ritorno della open ed utilizzarlo come file descriptor per una write.

Soluzione:

/∗ f i l e : e s 8 2 . c

∗ j o b : open

∗/

#include <u n i s t d . h>

#include < s t d l i b . h>

#include <s y s / t y p e s . h>

#include <s y s / s t a t . h>

#include < f c n t l . h>

#include < s t r i n g . h>

#include <s t d i o . h>

char msg [ 2 5 6 ] ;

i n t main ( i n t a r g c , char ∗∗ a r g v ) { i n t f d ;

i f ( a r g c <2) {

/∗ manca i l nome , usciamo ∗/

w r i t e ( 2 , ” I n s e r i r e i l nome d e l f i l e ! \ n” , 2 8 ) ; e x i t ( 1 ) ;

} e l s e {

f d=open ( a r g v [ 1 ] ,O WRONLY| O CREAT | O EXCL, 0 0 6 6 6 ) ; s n p r i n t f ( msg , s i z e o f ( msg ) , ” f d=%d\n” , f d ) ;

w r i t e ( 1 , msg , s t r l e n ( msg ) ) ; }

/∗ u t i l i z z i a m o l a w r i t e su f d : ∗/

return ( w r i t e ( fd , ” Ciao , Mondo ! \ n” , 1 3 ) ) ;

/∗ f d e ’ un nuovo f i l e d e s c r i p t o r c h e puo ’ e s s e r e

∗ u t i l i z z a t o e s a t t a m e n t e come s t d o u t o s t d e r r ∗/

}

10. Chiusura di un file: la funzione close. Modificare es82.c in modo che il file creato sia chiuso prima della terminazione.

Soluzione:

/∗ f i l e : e s 8 2 . c

∗ j o b : open , c l o s e

∗/

(7)

#include <u n i s t d . h>

#include < s t d l i b . h>

#include <s y s / t y p e s . h>

#include <s y s / s t a t . h>

#include < f c n t l . h>

#include < s t r i n g . h>

#include <s t d i o . h>

char msg [ 2 5 6 ] ;

i n t main ( i n t a r g c , char ∗∗ a r g v ) { i n t f d ;

i n t nw ; /∗ numero d i c a r a t t e r i s c r i t t i ∗/

i f ( a r g c <2) {

/∗ manca i l nome , usciamo ∗/

w r i t e ( 2 , ” I n s e r i r e i l nome d e l f i l e ! \ n” , 2 8 ) ; e x i t ( 1 ) ;

} e l s e {

f d=open ( a r g v [ 1 ] ,O WRONLY| O CREAT | O EXCL, 0 0 6 6 6 ) ; s n p r i n t f ( msg , s i z e o f ( msg ) , ” f d=%d\n” , f d ) ;

w r i t e ( 1 , msg , s t r l e n ( msg ) ) ; }

nw=w r i t e ( fd , ” Ciao , Mondo ! \ n” , 1 3 ) ; i f ( c l o s e ( f d ) ! = 0 ) {

w r i t e ( 2 , ” E r r o r e i n c h i u s u r a \n” , 2 0 ) ; }

return (nw ) ; }

11. (15 minuti) es83.c Utilizzo di un file esistente. Progettare un programma c che apra il file indicato dal primo argomento e sovrascriva i primi 4 caratteri con la stringa ”ciao”

Soluzione:

/∗ f i l e : e s 8 3 . c

∗ j o b : m o d i f i c a d i f i l e

∗/

#include <u n i s t d . h>

#include < s t d l i b . h>

#include <s y s / t y p e s . h>

#include <s y s / s t a t . h>

#include < f c n t l . h>

#include < s t r i n g . h>

#include <s t d i o . h>

char msg [ 2 5 6 ] ;

i n t main ( i n t a r g c , char ∗∗ a r g v ) { i n t f d ;

i n t nw ; /∗ numero d i c a r a t t e r i s c r i t t i ∗/

i f ( a r g c <2) {

/∗ manca i l nome , usciamo ∗/

w r i t e ( 2 , ” I n s e r i r e i l nome d e l f i l e ! \ n” , 2 8 ) ; e x i t ( 1 ) ;

} e l s e {

f d=open ( a r g v [ 1 ] ,O WRONLY) ;

s n p r i n t f ( msg , s i z e o f ( msg ) , ” f d=%d\n” , f d ) ;

(8)

w r i t e ( 1 , msg , s t r l e n ( msg ) ) ; i f ( fd <0) {

s n p r i n t f ( msg , s i z e o f ( msg ) , ” E r r o r e i n a p e r t u r a d i %s ” , a r g v [ 1 ] ) ; w r i t e ( 2 , msg , s t r l e n ( msg ) ) ;

e x i t ( 1 ) ; }

}

nw=w r i t e ( fd , ” c i a o ” , 4 ) ; i f ( c l o s e ( f d ) ! = 0 ) {

w r i t e ( 2 , ” E r r o r e i n c h i u s u r a \n” , 2 0 ) ; }

return (nw ) ; }

12. Cosa succede se il file vittima `e pi`u lungo di 4 caratteri? E se fosse pi`u corto?

Soluzione:

La dimensione finale del file e’ il massimo fra 4 ed il numero di caratteri precedente 13. Modificare es83.c in modo che il file venga troncato alla dimensione 4.

Soluzione:

/∗ f i l e : e s 8 3 . c

∗ j o b : m o d i f i c a d i f i l e

∗/

#include <u n i s t d . h>

#include < s t d l i b . h>

#include <s y s / t y p e s . h>

#include <s y s / s t a t . h>

#include < f c n t l . h>

#include < s t r i n g . h>

#include <s t d i o . h>

char msg [ 2 5 6 ] ;

i n t main ( i n t a r g c , char ∗∗ a r g v ) { i n t f d ;

i n t nw ; /∗ numero d i c a r a t t e r i s c r i t t i ∗/

i f ( a r g c <2) {

/∗ manca i l nome , usciamo ∗/

w r i t e ( 2 , ” I n s e r i r e i l nome d e l f i l e ! \ n” , 2 8 ) ; e x i t ( 1 ) ;

} e l s e {

f d=open ( a r g v [ 1 ] ,O WRONLY) ;

/∗ |O TRUNC a z z e r a l a l u n g h e z z a d e l f i l e a l l ’ a t t o

∗ d e l l a open ∗/

s n p r i n t f ( msg , s i z e o f ( msg ) , ” f d=%d\n” , f d ) ; w r i t e ( 1 , msg , s t r l e n ( msg ) ) ;

i f ( fd <0) {

s n p r i n t f ( msg , s i z e o f ( msg ) ,

” E r r o r e i n a p e r t u r a d i %s ” , a r g v [ 1 ] ) ; w r i t e ( 2 , msg , s t r l e n ( msg ) ) ;

e x i t ( 1 ) ; }

}

(9)

nw=w r i t e ( fd , ” c i a o ” , 4 ) ;

f t r u n c a t e ( fd , 4 ) ; /∗ t r o n c a m e n t o manuale ∗/

i f ( c l o s e ( f d ) ! = 0 ) {

w r i t e ( 2 , ” E r r o r e i n c h i u s u r a \n” , 2 0 ) ; }

return (nw ) ; }

14. (25 minuti) es84.c Lettura da file. Creare un sorgente c che legga i primi N caratteri (N<100) dal file F con N ed F rispettivamente primo e secondo argomento della command line.

Soluzione:

/∗ f i l e : e s 8 4 . c

∗ j o b : l e t t u r a d i N c a r a t t e r i da F

∗ uso : e s 8 4 N F

∗/

#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 t d l i b . h>

#include <s y s / t y p e s . h>

#include <s y s / s t a t . h>

#include < f c n t l . h>

char a r r a y [ 1 0 1 ] ; /∗ 100 + ’ \ 0 ’ ∗/

char msg [ 2 5 6 ] ; /∗ m e s s a g g i o ∗/

i n t f d ; /∗ f i l e d e s c r i p t o r ∗/

i n t N; /∗ primo a r g ∗/

char ∗F ; /∗ s e c o n d o a r g ∗/

i n t nr ; /∗ numero c h a r l e t t i ∗/

i n t main ( i n t a r g c , char ∗∗ a r g v ) { switch ( a r g c ) { /∗ num a r g s ∗/

case 3 :

N=a t o i ( a r g v [ 1 ] ) ; F=a r g v [ 2 ] ;

break ; d e f a u l t :

s n p r i n t f ( msg , s i z e o f ( msg ) ,

” uso : %s N F\n” , a r g v [ 0 ] ) ; w r i t e ( 2 , msg , s t r l e n ( msg ) ) ; e x i t ( 1 ) ;

}

f d=open (F ,O RDONLY ) ;

i f ( fd <0) { /∗ c h k open ∗/

s n p r i n t f ( msg , s i z e o f ( msg ) ,

” E r r o r e i n a p e r t u r a \n” ) ; w r i t e ( 2 , msg , s t r l e n ( msg ) ) ; e x i t ( 1 ) ;

}

i f (N>100) { /∗ c h k N ∗/

s n p r i n t f ( msg , s i z e o f ( msg ) ,

”N t r o p p o g r a n d e \n” ) ; w r i t e ( 2 , msg , s t r l e n ( msg ) ) ;

(10)

e x i t ( 1 ) ; }

nr=r e a d ( fd , a r r a y ,N ) ;

i f ( nr <0) { /∗ c h k r e a d ∗/

s n p r i n t f ( msg , s i z e o f ( msg ) ,

” E r r o r e i n l e t t u r a \n” ) ; w r i t e ( 2 , msg , s t r l e n ( msg ) ) ; e x i t ( 1 ) ;

}

a r r a y [ nr ]= ’ \0 ’ ; /∗ t e r m i n o l a s t r i n g a ∗/

s n p r i n t f ( msg , s i z e o f ( msg ) ,

” l e t t o : \n%s \ n T o t a l e %d c a r a t t e r i \n” , a r r a y , nr ) ; w r i t e ( 1 , msg , s t r l e n ( msg ) ) ;

return ( 0 ) ; }

15. (15 minuti) Modificare es84.c in modo che gli N caratteri letti siano copiati nello stesso file a partire dalla posizione K, con K terzo argomento.

Soluzione:

/∗ f i l e : e s 8 4 . c

∗ j o b : l e t t u r a d i N c a r a t t e r i da F

∗ e c o p i a i n p o s i z i o n e K

∗ uso : e s 8 4 N F K

∗/

#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 t d l i b . h>

#include <s y s / t y p e s . h>

#include <s y s / s t a t . h>

#include < f c n t l . h>

char a r r a y [ 1 0 1 ] ; /∗ 100 + ’ \ 0 ’ ∗/

char msg [ 2 5 6 ] ; /∗ m e s s a g g i o ∗/

i n t f d r ; /∗ f i l e d e s c r i p t o r , l e t t u r a ∗/

i n t fdw ; /∗ f i l e d e s c r i p t o r , s c r i t t u r a ∗/

i n t N; /∗ primo a r g ∗/

char ∗F ; /∗ s e c o n d o a r g ∗/

i n t K; /∗ t e r z o a r g ∗/

i n t nr ; /∗ numero c h a r l e t t i ∗/

i n t nw ; /∗ numero c h a r s c r i t t i ∗/

i n t main ( i n t a r g c , char ∗∗ a r g v ) { switch ( a r g c ) { /∗ num a r g s ∗/

case 4 :

N=a t o i ( a r g v [ 1 ] ) ; F=a r g v [ 2 ] ;

K=a t o i ( a r g v [ 3 ] ) ; break ;

d e f a u l t :

s n p r i n t f ( msg , s i z e o f ( msg ) ,

” uso : %s N F K\n” , a r g v [ 0 ] ) ; w r i t e ( 2 , msg , s t r l e n ( msg ) ) ;

(11)

e x i t ( 1 ) ; }

f d r=open (F ,O RDONLY ) ;

i f ( f d r <0) { /∗ c h k open ∗/

s n p r i n t f ( msg , s i z e o f ( msg ) ,

” E r r o r e i n a p e r t u r a ( rd ) \ n” ) ; w r i t e ( 2 , msg , s t r l e n ( msg ) ) ; e x i t ( 1 ) ;

}

i f (N>100) { /∗ c h k N ∗/

s n p r i n t f ( msg , s i z e o f ( msg ) ,

”N t r o p p o g r a n d e \n” ) ; w r i t e ( 2 , msg , s t r l e n ( msg ) ) ; e x i t ( 1 ) ;

}

nr=r e a d ( f d r , a r r a y ,N ) ; i f ( nr <0) { /∗ c h k r e a d ∗/

s n p r i n t f ( msg , s i z e o f ( msg ) ,

” E r r o r e i n l e t t u r a \n” ) ; w r i t e ( 2 , msg , s t r l e n ( msg ) ) ; e x i t ( 1 ) ;

}

fdw=open (F ,O WRONLY) ;

i f ( fdw <0) { /∗ c h k open ∗/

s n p r i n t f ( msg , s i z e o f ( msg ) ,

” E r r o r e i n a p e r t u r a ( wr ) \ n” ) ; w r i t e ( 2 , msg , s t r l e n ( msg ) ) ; e x i t ( 1 ) ;

}

i f ( l s e e k ( fdw , K, SEEK SET) ! =K) { /∗ r e t v a l=p o s i z i o n e ∗/

s n p r i n t f ( msg , s i z e o f ( msg ) ,

” E r r o r e n e l p o s i z i o n a m e n t o \n” ) ; w r i t e ( 2 , msg , s t r l e n ( msg ) ) ;

e x i t ( 1 ) ; }

nw=w r i t e ( fdw , a r r a y , nr ) ; s n p r i n t f ( msg , s i z e o f ( msg ) ,

” L e t t i %d c a r a t t e r i \n”

” C o p i a t i %d c a r a t t e r i a l l a p o s i z i o n e %d\n” , nr , nw ,K ) ;

w r i t e ( 1 , msg , s t r l e n ( msg ) ) ; return ( 0 ) ;

}

16. Utilizzando la funzione fork() creare un nuovo processo (es85.c) Soluzione:

/∗ f i l e : e s 8 5 . c

∗ j o b : uso d e l l a f o r k

∗/

#include <s y s / t y p e s . h>

#include <u n i s t d . h>

i n t main ( i n t a r g c , char ∗∗ a r g v ) {

(12)

f o r k ( ) ; return ( 0 ) ; }

17. Presentare su stdout il valore ritornato dalla fork(). Si utilizzi la coppia snprintf()/write() al posto della semplice printf()

Soluzione:

/∗ f i l e : e s 8 5 . c

∗ j o b : uso d e l l a f o r k

∗/

#include <s y s / t y p e s . h>

#include <u n i s t d . h>

#include <s t d i o . h>

#include <u n i s t d . h>

#include < s t r i n g . h>

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 f r ; /∗ f o r k r e t u r n v a l u e ∗/

f r=f o r k ( ) ;

s n p r i n t f ( msg , s i z e o f ( msg ) ,

” f o r k : %d\n” , f r ) ; w r i t e ( 1 , msg , s t r l e n ( msg ) ) ; return ( 0 ) ;

}

18. Per quale motivo troviamo su stdout due messaggi (con valori differenti)?

Soluzione:

La funzione fork() invoca la system call omonima che provoca la creazione di un nuovo processo ’clonando’ quello corrente.

Il processo ’originale’, detto padre, ottiene dalla fork un numero intero strettamente positivo che rappresenta il pid del nuovo processo creato

Il nuovo processo, detto ’figlio’, si trova con una copia esatta del processo padre e, quindi, iniziera’ la sua esecuzione dall’istruzione (macchina) appena successiva alla chiamata a fork(). Il valore di ritorno recuperato dal figlio, tuttavia, e’ diverso da quello che ha ottenuto il processo padre ed e’ sempre uguale a 0.

Utilizzando questa differenza, sara’ possibile determinare a programma se il codice viene eseguito dal padre o dal figlio operando in modo diverso.

19. Verificare il ruolo di padre e figlio visualizzandolo su standard output.

Soluzione:

/∗ f i l e : e s 8 5 . c

∗ j o b : uso d e l l a f o r k

∗/

#include <s y s / t y p e s . h>

#include <u n i s t d . h>

#include <s t d i o . h>

#include <u n i s t d . h>

(13)

#include < s t r i n g . h>

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 f r ; /∗ f o r k r e t u r n v a l u e ∗/

f r=f o r k ( ) ;

i f ( f r ==0) { /∗ f i g l i o ∗/

s n p r i n t f ( msg , s i z e o f ( msg ) , ” F i g l i o \n” ) ; w r i t e ( 1 , msg , s t r l e n ( msg ) ) ;

} e l s e { /∗ p a d r e ∗/

s n p r i n t f ( msg , s i z e o f ( msg ) ,

” Padre d e l f i g l i o %d\n” , f r ) ; w r i t e ( 1 , msg , s t r l e n ( msg ) ) ;

}

return ( 0 ) ; }

20. La funzione fork() restituisce -1 in caso di errore (e, ovviamente, non genera il nuovo processo). Ag- giungere questa verifica associandola ad un opportuno messaggio d’errore.

Soluzione:

/∗ f i l e : e s 8 5 . c

∗ j o b : uso d e l l a f o r k

∗/

#include <s y s / t y p e s . h>

#include <u n i s t d . h>

#include <s t d i o . h>

#include <u n i s t d . h>

#include < s t r i n g . h>

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 f r ; /∗ f o r k r e t u r n v a l u e ∗/

f r=f o r k ( ) ; switch ( f r ) {

case 0 : /∗ f i g l i o ∗/

s n p r i n t f ( msg , s i z e o f ( msg ) , ” F i g l i o \n” ) ; w r i t e ( 1 , msg , s t r l e n ( msg ) ) ;

break ;

case −1: /∗ e r r o r e , n e s s u n nuovo p r o c e s s o ∗/

s n p r i n t f ( msg , s i z e o f ( msg ) , ” E r r o r e i n f o r k \n” ) ; w r i t e ( 1 , msg , s t r l e n ( msg ) ) ;

break ;

d e f a u l t : /∗ p a d r e ∗/

s n p r i n t f ( msg , s i z e o f ( msg ) ,

” Padre d e l f i g l i o %d\n” , f r ) ; w r i t e ( 1 , msg , s t r l e n ( msg ) ) ;

}

return ( 0 ) ; }

21. Sia il processo padre che il processo figlio hanno un proprio exit value. Utilizzare la funzione wait() per recuperare l’exit value del processo figlio.

Soluzione:

(14)

/∗ f i l e : e s 8 5 . c

∗ j o b : uso d e l l a f o r k

∗/

#include <s y s / t y p e s . h>

#include <u n i s t d . 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 y s / w a i t . h>

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 f r ; /∗ f o r k r e t u r n v a l u e ∗/

i n t s t ; /∗ s p a z i o p e r l ’ e x i t v a l u e ∗/

f r=f o r k ( ) ; switch ( f r ) {

case 0 : /∗ f i g l i o ∗/

s n p r i n t f ( msg , s i z e o f ( msg ) , ” F i g l i o \n” ) ; w r i t e ( 1 , msg , s t r l e n ( msg ) ) ;

return ( 4 ) ; /∗ e x i t v a l u e d e l f i g l i o ∗/

break ;

case −1: /∗ e r r o r e , n e s s u n nuovo p r o c e s s o ∗/

s n p r i n t f ( msg , s i z e o f ( msg ) , ” E r r o r e i n f o r k \n” ) ; w r i t e ( 1 , msg , s t r l e n ( msg ) ) ;

break ;

d e f a u l t : /∗ p a d r e ∗/

s n p r i n t f ( msg , s i z e o f ( msg ) ,

” Padre d e l f i g l i o %d\n” , f r ) ; w r i t e ( 1 , msg , s t r l e n ( msg ) ) ;

/∗ uso l a w a i t p e r a t t e n d e r e i l p r o c e s s o

∗ f i g l i o e r e c u p e r a r e i l suo e x i t v a l u e ∗/

w a i t (& s t ) ;

s n p r i n t f ( msg , s i z e o f ( msg ) ,

” E x i t v a l u e : %d\n” ,WEXITSTATUS( s t ) ) ; w r i t e ( 1 , msg , s t r l e n ( msg ) ) ;

}

return ( 0 ) ; }

22. La wait svolge anche un ruolo di sincronizzazione fra processo padre e processo figlio?

Soluzione:

Se proviamo ad eseguire diverse volte il programma es85, potremmo notare che la sequenza con la quale vediamo il messaggio "Figlio..."

e quello "Padre..." non e’ ripetitiva. La stampa di "Exit...", al contrario, sara’ sempre successiva a "Figlio..." anche se operate da processi differenti.

Questo e’ dovuto alla presenza della chiamata a wait() che, per recuperare l’exit value del figlio, deve forzare il processo corrente (padre) ad attendere (wait, appunto) la terminazione del processo figlio.

23. (25 minuti) es86.c Condivisione di file. Si progetti una applicazione concorrente composta da due processi, padre e figlio, tali che il file rappresentato dal primo argomento sia aperto prima della fork() ed utilizzato in lettura in modo condiviso per contare i caratteri contenuti leggendoli ad uno ad uno.

(15)

Soluzione:

/∗ f i l e : e s 8 6 . c

∗ j o b : f i l e c o n d i v i s o

∗/

#include <s y s / t y p e s . h>

#include <u n i s t d . 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 y s / w a i t . h>

#include <s y s / s t a t . h>

#include < f c n t l . h>

char msg [ 2 5 6 ] ; i n t f d ;

i n t main ( i n t a r g c , char ∗∗ a r g v ) {

p i d t f r ; /∗ f o r k r e t u r n v a l u e ∗/

i n t s t ; /∗ s p a z i o p e r l ’ e x i t v a l u e ∗/

i n t c o u n t ; /∗ c o n t a t o r e d i r e a d ∗/

char ch ; /∗ s p a z i o p e r l a r e a d ∗/

f d=open ( a r g v [ 1 ] , O RDONLY ) ; i f ( fd <0) return ( − 1 ) ; f r=f o r k ( ) ;

switch ( f r ) {

case 0 : /∗ f i g l i o ∗/

f o r ( c o u n t =0; r e a d ( fd ,& ch ,1)==1; c o u n t ++);

s n p r i n t f ( msg , s i z e o f ( msg ) , ” F i g l i o c o n t a %d\n” , c o u n t ) ; w r i t e ( 1 , msg , s t r l e n ( msg ) ) ;

return ( 4 ) ; /∗ e x i t v a l u e d e l f i g l i o ∗/

break ;

case −1: /∗ e r r o r e , n e s s u n nuovo p r o c e s s o ∗/

s n p r i n t f ( msg , s i z e o f ( msg ) , ” E r r o r e i n f o r k \n” ) ; w r i t e ( 1 , msg , s t r l e n ( msg ) ) ;

break ;

d e f a u l t : /∗ p a d r e ∗/

f o r ( c o u n t =0; r e a d ( fd ,& ch ,1)==1; c o u n t ++);

s n p r i n t f ( msg , s i z e o f ( msg ) ,

” Padre d e l f i g l i o %d , c o n t a : %d\n” , f r , c o u n t ) ;

w r i t e ( 1 , msg , s t r l e n ( msg ) ) ;

/∗ uso l a w a i t p e r a t t e n d e r e i l p r o c e s s o

∗ f i g l i o e r e c u p e r a r e i l suo e x i t v a l u e ∗/

w a i t (& s t ) ;

s n p r i n t f ( msg , s i z e o f ( msg ) ,

” E x i t v a l u e : %d\n” ,WEXITSTATUS( s t ) ) ; w r i t e ( 1 , msg , s t r l e n ( msg ) ) ;

}

return ( 0 ) ; }

24. Creare un Makefile per la compilazione di es86.

Soluzione:

#! / b i n /make −f

(16)

# f i l e : M a k e f i l e

# f o r m a t o d e l l a r e g o l a = o b i e t t i v o : d i p e n d e n z e e s 8 6 : e s 8 6 . c

g c c −Wall −o e s 8 6 e s 8 6 . c

# R i c o r d a r s i d e l t a b a l l ’ i n i z i o d i o g n i comando

25. (10 minuti) es87.c Comportamento della printf in applicazioni concorrenti. Creare un sorgente che utilizzi la printf per emettere una stringa priva di fine linea prima della fork().

Soluzione:

/∗ f i l e : e s 8 7 . c

∗ j o b : f o r k e p r i n t f , una v e r i f i c a

∗/

#include <s y s / t y p e s . h>

#include <u n i s t d . h>

#include <s t d i o . h>

char s t r i n g a [ 2 5 6 ] ;

i n t main ( i n t a r g c , char ∗∗ a r g v ) {

/∗ s u b i t o una p r i n t f s e n z a \n ∗/

p r i n t f ( ” Prima d e l l a f o r k ( ) : ” ) ; switch ( f o r k ( ) ) {

case 0 : /∗ f i g l i o ∗/

p r i n t f ( ” f i g l i o \n” ) ; return ( 0 ) ;

case −1:

p r i n t f ( ” e r r o r e \n” ) ; return ( 1 ) ;

d e f a u l t :

p r i n t f ( ” p a d r e \n” ) ; return ( 0 ) ;

} }

26. L’esecuzione di es87 riporta la stringa iniziale per due volte su stdout. Proviamo a modificare il sorgente introducendo la write al posto della printf.

Soluzione:

/∗ f i l e : e s 8 7 . c

∗ j o b : f o r k e p r i n t f , una v e r i f i c a

∗/

#include <s y s / t y p e s . h>

#include <u n i s t d . h>

char s t r i n g a [ 2 5 6 ] ;

i n t main ( i n t a r g c , char ∗∗ a r g v ) {

/∗ s u b i t o una p r i n t f s e n z a \n ∗/

w r i t e ( 1 , ” Prima d e l l a f o r k ( ) : ” , 2 0 ) ; switch ( f o r k ( ) ) {

case 0 : /∗ f i g l i o ∗/

w r i t e ( 1 , ” f i g l i o \n” , 7 ) ; return ( 0 ) ;

case −1:

w r i t e ( 1 , ” e r r o r e \n” , 7 ) ;

(17)

return ( 1 ) ; d e f a u l t :

w r i t e ( 1 , ” p a d r e \n” , 6 ) ; return ( 0 ) ;

} }

27. (15 minuti) es88.c Creazione di pi`u processi. Creare un sorgente che generi un numero di figli uguale al numero passato come primo argomento.

Soluzione:

/∗ f i l e : e s 8 8 . c

∗ j o b : f o r k ( ) m u l t i p l a

∗/

#include <s y s / t y p e s . h>

#include <u n i s t d . h>

#include < s t d l i b . h>

#include <s t d i o . h>

#include < s t r i n g . h>

char s t r i n g a [ 2 5 6 ] ;

i n t main ( i n t a r g c , char ∗∗ a r g v ) { i n t n f i g l i ; /∗ N ∗/

i n t i n d i c e ; /∗ i n d i c e d i c r e a z i o n e ∗/

i n t p i d ; /∗ p r o c e s s i d e n t i f i e r ∗/

i f ( a r g c <2) {

s n p r i n t f ( s t r i n g a , 2 5 6 , ” Uso : %s N\n” , a r g v [ 0 ] ) ; w r i t e ( 2 , s t r i n g a , s t r l e n ( s t r i n g a ) ) ;

return ( 1 ) ; } e l s e {

n f i g l i =a t o i ( a r g v [ 1 ] ) ; }

f o r ( i n d i c e =0; i n d i c e < n f i g l i ; i n d i c e ++) { p i d=f o r k ( ) ;

switch ( p i d ) {

case 0 : /∗ f i g l i o ∗/

return ( 0 ) ; /∗ t e r m i n a z i o n e ∗/

case −1: /∗ e r r o r e ∗/

s n p r i n t f ( s t r i n g a , 2 5 6 , ” E r r o r e a l l a %d−ma f o r k \n” , i n d i c e ) ; w r i t e ( 2 , s t r i n g a , s t r l e n ( s t r i n g a ) ) ;

return ( 1 ) ; /∗ t e r m i n a z i o n e p a d r e ∗/

d e f a u l t : /∗ padre , c o n t i n u a ∗/

s n p r i n t f ( s t r i n g a , 2 5 6 , ” C r e a t o f i g l i o %d con p i d %d\n” , i n d i c e , p i d ) ;

w r i t e ( 1 , s t r i n g a , s t r l e n ( s t r i n g a ) ) ; }

}

/∗ i l p a d r e a r r i v a q u i dopo l e N c r e a z i o n i ∗/

return ( 0 ) ; }

28. (10 minuti) es88.c Modificare es88.c in modo che ogni figlio stampi su stdout il proprio indice.

Soluzione:

(18)

/∗ f i l e : e s 8 8 . c

∗ j o b : f o r k ( ) m u l t i p l a

∗/

#include <s y s / t y p e s . h>

#include <u n i s t d . h>

#include < s t d l i b . h>

#include <s t d i o . h>

#include < s t r i n g . h>

char s t r i n g a [ 2 5 6 ] ;

i n t main ( i n t a r g c , char ∗∗ a r g v ) { i n t n f i g l i ; /∗ N ∗/

i n t i n d i c e ; /∗ i n d i c e d i c r e a z i o n e ∗/

i n t p i d ; /∗ p r o c e s s i d e n t i f i e r ∗/

i f ( a r g c <2) {

s n p r i n t f ( s t r i n g a , 2 5 6 , ” Uso : %s N\n” , a r g v [ 0 ] ) ; w r i t e ( 2 , s t r i n g a , s t r l e n ( s t r i n g a ) ) ;

return ( 1 ) ; } e l s e {

n f i g l i =a t o i ( a r g v [ 1 ] ) ; }

f o r ( i n d i c e =0; i n d i c e < n f i g l i ; i n d i c e ++) { p i d=f o r k ( ) ;

switch ( p i d ) {

case 0 : /∗ f i g l i o ∗/

s n p r i n t f ( s t r i n g a , 2 5 6 , ” F i g l i o con i n d i c e %d\n” , i n d i c e ) ; w r i t e ( 1 , s t r i n g a , s t r l e n ( s t r i n g a ) ) ;

return ( 0 ) ; /∗ t e r m i n a z i o n e ∗/

case −1: /∗ e r r o r e ∗/

s n p r i n t f ( s t r i n g a , 2 5 6 , ” E r r o r e a l l a %d−ma f o r k \n” , i n d i c e ) ; w r i t e ( 2 , s t r i n g a , s t r l e n ( s t r i n g a ) ) ;

return ( 1 ) ; /∗ t e r m i n a z i o n e p a d r e ∗/

d e f a u l t : /∗ padre , c o n t i n u a ∗/

s n p r i n t f ( s t r i n g a , 2 5 6 , ” C r e a t o f i g l i o %d con p i d %d\n” , i n d i c e , p i d ) ;

w r i t e ( 1 , s t r i n g a , s t r l e n ( s t r i n g a ) ) ; }

}

/∗ i l p a d r e a r r i v a q u i dopo l e N c r e a z i o n i ∗/

return ( 0 ) ; }

29. (15 minuti) es88.c Recupero degli exit value dei processi figli: modificare es88.c in modo che il processo padre attenda la terminazione di tutti i processi figli riportando su stdout gli exit value di ogni processo accanto al pid del processo terminato.

Soluzione:

/∗ f i l e : e s 8 8 . c

∗ j o b : f o r k ( ) m u l t i p l a

∗/

#include <s y s / t y p e s . h>

#include <u n i s t d . h>

#include < s t d l i b . h>

#include <s t d i o . h>

(19)

#include < s t r i n g . h>

#include <s y s / w a i t . h>

char s t r i n g a [ 2 5 6 ] ;

i n t main ( i n t a r g c , char ∗∗ a r g v ) { i n t n f i g l i ; /∗ N ∗/

i n t i n d i c e ; /∗ i n d i c e d i c r e a z i o n e ∗/

i n t p i d ; /∗ p r o c e s s i d e n t i f i e r ∗/

i n t s t ; /∗ e x i t s t a t u s ∗/

i f ( a r g c <2) {

s n p r i n t f ( s t r i n g a , 2 5 6 , ” Uso : %s N\n” , a r g v [ 0 ] ) ; w r i t e ( 2 , s t r i n g a , s t r l e n ( s t r i n g a ) ) ;

return ( 1 ) ; } e l s e {

n f i g l i =a t o i ( a r g v [ 1 ] ) ; }

f o r ( i n d i c e =0; i n d i c e < n f i g l i ; i n d i c e ++) { p i d=f o r k ( ) ;

switch ( p i d ) {

case 0 : /∗ f i g l i o ∗/

s n p r i n t f ( s t r i n g a , 2 5 6 , ” F i g l i o con i n d i c e %d\n” , i n d i c e ) ; w r i t e ( 1 , s t r i n g a , s t r l e n ( s t r i n g a ) ) ;

return ( 0 ) ; /∗ t e r m i n a z i o n e ∗/

case −1: /∗ e r r o r e ∗/

s n p r i n t f ( s t r i n g a , 2 5 6 , ” E r r o r e a l l a %d−ma f o r k \n” , i n d i c e ) ; w r i t e ( 2 , s t r i n g a , s t r l e n ( s t r i n g a ) ) ;

return ( 1 ) ; /∗ t e r m i n a z i o n e p a d r e ∗/

d e f a u l t : /∗ padre , c o n t i n u a ∗/

s n p r i n t f ( s t r i n g a , 2 5 6 , ” C r e a t o f i g l i o %d con p i d %d\n” , i n d i c e , p i d ) ;

w r i t e ( 1 , s t r i n g a , s t r l e n ( s t r i n g a ) ) ; }

}

/∗ i l p a d r e a r r i v a q u i dopo l e N c r e a z i o n i ∗/

f o r ( i n d i c e =0; i n d i c e < n f i g l i ; i n d i c e ++) {

/∗ l ’ o r d i n e i n c u i i f i g l i t e r m i n a n o NON e ’ p r e v e d i b i l e ,

∗ q u i n d i i l v a l o r e r e c u p e r a t o a l l a i −esima i t e r a z i o n e

∗ non n e c e s s a r i a m e n t e s i r i f e r i s c e a l l ’ i −esimo

∗ f i g l i o . ∗/

p i d=w a i t (& s t ) ;

s n p r i n t f ( s t r i n g a , 2 5 6 , ” 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 ) ) ;

w r i t e ( 1 , s t r i n g a , s t r l e n ( s t r i n g a ) ) ; }

return ( 0 ) ; }

30. Un po’ di ordine: modifichiamo es88.c in modo che le operazioni delegate ai processi figli siano incluse in una funzione.

Soluzione:

/∗ f i l e : e s 8 8 . c

∗ j o b : f o r k ( ) m u l t i p l a

∗/

(20)

#include <s y s / t y p e s . h>

#include <u n i s t d . h>

#include < s t d l i b . h>

#include <s t d i o . h>

#include < s t r i n g . h>

#include <s y s / w a i t . h>

char s t r i n g a [ 2 5 6 ] ;

/∗ P r o t o t i p o d e l l a 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 argomento ) ;

i n t main ( i n t a r g c , char ∗∗ a r g v ) { i n t n f i g l i ; /∗ N ∗/

i n t i n d i c e ; /∗ i n d i c e d i c r e a z i o n e ∗/

i n t p i d ; /∗ p r o c e s s i d e n t i f i e r ∗/

i n t s t ; /∗ e x i t s t a t u s ∗/

i f ( a r g c <2) {

s n p r i n t f ( s t r i n g a , 2 5 6 , ” Uso : %s N\n” , a r g v [ 0 ] ) ; w r i t e ( 2 , s t r i n g a , s t r l e n ( s t r i n g a ) ) ;

return ( 1 ) ; } e l s e {

n f i g l i =a t o i ( a r g v [ 1 ] ) ; }

f o r ( i n d i c e =0; i n d i c e < n f i g l i ; i n d i c e ++) { p i d=f o r k ( ) ;

switch ( p i d ) {

case 0 : /∗ f i g l i o ∗/

/∗ c h i a m a t a a l l a f u n z i o n e f i g l i o

∗ e r e c u p e r o d e l v a l o r e d i

∗ r i t o r n o ∗/

return ( f i g l i o ( i n d i c e ) ) ; case −1: /∗ e r r o r e ∗/

s n p r i n t f ( s t r i n g a , 2 5 6 , ” E r r o r e a l l a %d−ma f o r k \n” , i n d i c e ) ; w r i t e ( 2 , s t r i n g a , s t r l e n ( s t r i n g a ) ) ;

return ( 1 ) ; /∗ t e r m i n a z i o n e p a d r e ∗/

d e f a u l t : /∗ padre , c o n t i n u a ∗/

s n p r i n t f ( s t r i n g a , 2 5 6 , ” C r e a t o f i g l i o %d con p i d %d\n” , i n d i c e , p i d ) ;

w r i t e ( 1 , s t r i n g a , s t r l e n ( s t r i n g a ) ) ; }

}

/∗ i l p a d r e a r r i v a q u i dopo l e N c r e a z i o n i ∗/

f o r ( i n d i c e =0; i n d i c e < n f i g l i ; i n d i c e ++) {

/∗ l ’ o r d i n e i n c u i i f i g l i t e r m i n a n o NON e ’ p r e v e d i b i l e ,

∗ q u i n d i i l v a l o r e r e c u p e r a t o a l l a i −esima i t e r a z i o n e

∗ non n e c e s s a r i a m e n t e s i r i f e r i s c e a l l ’ i −esimo

∗ f i g l i o . ∗/

p i d=w a i t (& s t ) ;

s n p r i n t f ( s t r i n g a , 2 5 6 , ” 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 ) ) ;

w r i t e ( 1 , s t r i n g a , s t r l e n ( s t r i n g a ) ) ; }

return ( 0 ) ; }

/∗ Corpo d e l l a f u n z i o n e f i g l i o ∗/

(21)

i n t f i g l i o ( i n t argomento ) {

/∗ usa s t r i n g a p e r c h e ’ e ’ una v a r i a b i l e g l o b a l e ∗/

s n p r i n t f ( s t r i n g a , 2 5 6 , ” F i g l i o con i n d i c e %d\n” , argomento ) ; w r i t e ( 1 , s t r i n g a , s t r l e n ( s t r i n g a ) ) ;

return ( 0 ) ; }

Riferimenti

Documenti correlati

(20 minuti circa) Creare uno script per la creazione automatica di uno script. Si salvi il file con il nome crea script.sh. Il nome del file da creare deve essere creato partendo da

(20 minuti) Creare uno script che controlli di essere invocato con esattamente 2 argomenti e, se il primo argomento rappresenta una directory esistente e scrivibile, allora creare

(30 minuti) es47p.sh Controllo parametri della parte shell del compito del 7 luglio 2009: La parte in Shell deve prevedere due parametri: il primo deve essere il nome assoluto di

(40 minuti) es51p.sh Controllo parametri della parte shell del compito del 17 luglio 2007: La parte in Shell deve prevedere tre parametri: il primo deve essere il nome assoluto di

(15 minuti) es62p.sh Controllo parametri della parte shell del compito del 6 febbraio 2009 : La parte in Shell deve prevedere tre parametri: il primo deve essere il nome assoluto di

, FN e riportare su stdout un carattere di ogni file indicato, il primo carattere del primo file F1, l’ultimo carat- tere dell’ultimo file FN, il secondo carattere del secondo file

Far creare al padre N processi (con N valore del primo argomento) ed utilizzare una singola pipe per passare una struttura di dati da ogni figlio al

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;