Licence Informatique Système d’exploitation Multi-Processing - premiers pas Exercice 1 : Exécution concurrente des processus père et fils Ecrire un programme qui crée un fils. 3 Le père affiche : « Je suis le père mon PID est ... et mon PPID est ... ». 3 Le fils affiche : « Je suis le fils mon PID est ... et mon PPID est ... ». Rajouter l’appel à la primitive sleep pour voir les exécutions possibles : 1. Le fils se termine avant le père, 2. Le père se termine avant le fils. #include < s t d i o . h> #include <u n i s t d . h> void main ( ) { pid_t p ; p=f o r k ( ) ; switch ( p ) { case ( 0 ) : // s l e e p ( 1 5 ) ; p r i n t f ( " Le f i l s p i d e s t =%d e t mon p p i d e s t=%d\n" , getpid () , getppid ( ) ) ; break ; case ( − 1 ) : // s l e e p ( 1 5 ) ; p r i n t f ( " E r r e u r f o r k \n" ) ; break ; default : p r i n t f ( " Le p e r e p i d e s t =%d e t mon p p i d e s t=%d\n" , getpid () , getppid ( ) ) ; } p r i n t f ( " Fin du p r o c e s s u s %d\n" , g e t p i d ( ) ) ; } Exercice 2 : Héritage des attributs et copies des variables Reprendre le programme ci-dessus et compléter en affichant l’uid, le gid, et le contenu d’une variable x initialisée à 2 (avant le fork) et modifié selon x+3 par le fils et selon x*5 par le père. #include<u n i s t d . h> #include<s t d i o . h> void main ( ) { pid_t p ; int x = 2 ; p=f o r k ( ) ; switch ( p ) { case ( 0 ) : x = x + 3; p r i n t f ( " Le f i l s p i d=%d p p i d=%d u i d=%d g i d=%d x=%d\n" , getpid () , getppid () , getuid () , getgid () , Université de Pau et des Pays de l’Adour Licence Informatique Système d’exploitation x); break ; case ( − 1 ) : p r i n t f ( " E r r e u r f o r k \n" ) ; break ; default : x = x ∗ 5; p r i n t f ( " Le f i l s p i d=%d p p i d=%d u i d=%d g i d=%d x=%d\n" , g e t p i d ( ) , getppid () , getuid () , getgid () , x); } p r i n t f ( " Fin programme \n" ) ; } Exercice 3 : Cas particulier des descripteurs de fichiers Ecrire un programme qui ouvre un fichier nommé « toto », en lecture et écriture, dont le contenu est la suite 123456789. Le programme fork ensuite ; le fils écrit ab dans le fichier ensuite il s’endort et il lit 2 caractères ; le père s’endort, lit 2 caractères et écrit AB. /∗ Le d e s c r i p t e u r n e s t pas d u p l i q u é c a r i l e s t s t o c k é dans l a t b l d e s f i c h i e r s ∗/ /∗ e t non dans l a t b l d e s d e s c r i p t e u r ( p r o p r e à chaque p c s ) ∗/ #include<s t d i o . h> #include<f c n t l . h> #include<u n i s t d . h> #include<s y s / s t a t . h> #include<s y s / t y p e s . h> void main ( ) { pid_t p ; char c h a i n e [ 3 ] ; int desc ; d e s c=open ( " t o t o " ,O_RDWR, 0 ) ; p=f o r k ( ) ; switch ( p ) { case ( 0 ) : p r i n t f ( " Le f i l s PID=%d PPID=%d\n" , getpid () , getppid ( ) ) ; read ( desc , chaine , 2 ) ; c h a i n e [ 2 ] = ’ \0 ’ ; p r i n t f ( " c h a i n e l u e pa r l e f i l s %s \n" , c h a i n e ) ; sleep (10); c l o s e ( desc ) ; break ; case ( − 1 ) : p r i n t f ( " E r r e u r f o r k \n" ) ; break ; default : p r i n t f ( " Le p è r e V a l e u r de r e t o u r du f o r k=%d\n" , p ) ; p r i n t f ( " Le p è r e PID=%d PPID=%d\n" , getpid () , getppid ( ) ) ; sleep (3); read ( desc , chaine , 2 ) ; c h a i n e [ 2 ] = ’ \0 ’ ; p r i n t f ( " c h a i n e l u e pa r l e p è r e %s \n" , c h a i n e ) ; sleep (20); w r i t e ( d e s c , "AB" , 2 ) ; c l o s e ( desc ) ; } p r i n t f ( " Fin du Programme\n" ) ; } Exercice 4 : Synchronisation des processus père et fils par le wait Ecrire un programme qui crée un fils et affiche, pour chacun des processus le PID et PPID dans l’ordre : Fils puis père si l’on passe « synchro » comme paramètre, exécution des processus dans l’ordre décidé par l’ordonnanceur sinon. Université de Pau et des Pays de l’Adour Licence Informatique Système d’exploitation #include<u n i s t d . h> #include<s t d i o . h> #include<e r r n o . h> #include<s t r i n g . h> void main ( i n t a r g c , char ∗ a r g v [ ] ) { pid_t p i d ; int s t a t u t ; i f ( ( a r g c ==2) && ( strcmp ( a r g v [ 1 ] , " s y n c h r o " ) ! = 0 ) ) { p r i n t f ( " L a n c e r l e programme a v e c un argument : \ n" ) ; p r i n t f ( " \ t Synchro pour a f f i c h e r l e f i l s p u i s l e p e r e \n" ) ; p r i n t f ( "Aucun argument s i n o n . \n" ) ; } else { s ys tem ( " c l e a r " ) ; p r i n t f ( " \n\ t \ t \tGENERATION AUTOMATIQUE DE PROCESSUS\n\n" ) ; pid = f o r k ( ) ; switch ( p i d ) { case −1: perror (" erreur fork :\ t" ) ; break ; case 0 : sleep (1); p r i n t f ( " f i l s PID : %d \ t PPID : %d\n" , getpid () , getppid ( ) ) ; break ; default : i f ( ( a r g c ==2) && ( strcmp ( a r g v [ 1 ] , " s y n c h r o " )==0)) { w a i t (& s t a t u t ) ; p r i n t f ( " p e r e PID : %d \ t PPID : %d\n" , getpid () , getppid ( ) ) ; } else { p r i n t f ( " p e r e PID : %d \ t PPID : %d\n" , getpid () , getppid ( ) ) ; w a i t (& s t a t u t ) ; } /∗ E v i t e r un p r o c e s s u s zombie ∗/ } p r i n t f ( " \n\ t F i n du programme . PID : %d\n" , g e t p i d ( ) ) ; } } Exercice 5 : Attente et passage de paramètres Ecrire un programme dont le fonctionnement est le suivant :Il lit sur la ligne de commande (utiliser argc et argv) le nombre N de processus à créer. Il crée ces N processus en faisant N appels à fork (cf. plus loin la tâche assignée à ces processus).Il se met en attente (appel à Pid_Fils = wait(&Etat)) de ces N processus fils et visualise leur identité (Pid_Fils et valeur de Etat) au fur et à mesure de leurs terminaisons (Pour attendre la fin de tous les fils, utiliser le fait que wait renvoie la valeur -1 quand il n’y a plus de processus fils à attendre). Chacun des processus fils Pi exécute les instructions suivantes : il visualise son pid (getpid) et celui de son père (getppid), puis il se met en attente pendant 2*i secondes (sleep (2*i)), et visualise la fin de l’attente, puis se termine par exit (i). #include<u n i s t d . h> #include<s y s / w a i t . h> #include<s t d i o . h> #include<s t d l i b . h> #include<e r r n o . h> #include<s t r i n g . h> i n t main ( i n t a r g c , char ∗ a r g v [ ] ) { pid_t pid , p i d F i l s ; int statut , i , iReturn ; Université de Pau et des Pays de l’Adour Licence Informatique Système d’exploitation i n t iNbProc ; i f ( argc !=2) { p r i n t f ( " L a n c e r l e programme a v e c un argument : \ n" ) ; p r i n t f ( " \ t l e nombre de p r o c e s s u s f i l s a c r e e r \n" ) ; } else { s ys tem ( " c l e a r " ) ; p r i n t f ( " \n\ t \ t \tATTENTE AUTOMATIQUE DE LA TERMINAISON DES FILS \n\n" ) ; iNbProc = a t o i ( a r g v [ 1 ] ) ; f o r ( i =0; i <iNbProc ; i ++) { pid = f o r k ( ) ; i f ( p i d==−1){ perror ( " Creation f i l s " ) ; e x i t ( −1); } else i f ( pid !=0){ /∗ code p e r e ∗/ continue ; } else { /∗ code f i l s ∗/ p i d F i l s=g e t p i d ( ) ; f p r i n t f ( stdout , " F i l s num:%d de p i d %d e t de %d\n" , i , pidFils , getppid ( ) ) ; s l e e p (2∗ i ) ; f p r i n t f ( stdout , " F i l s num:%d de p i d %d e t j e me t e r m i n e \n" , i , pidFils ); exit ( i ); } } /∗ Les f i l s s o n t c r e e s . Le p e r e s e met en a t t e n t e ∗/ while ( 1 ) { i R e t u r n=w a i t (& s t a t u t ) ; i f ( i R e t u r n==−1) break ; /∗ r e t u r n −1 quand i l ne r e s t e p l u s de f i l s a a t t e n d r e ∗/ else { /∗ l a f o n c t i o n WEXITSTATUS r e t o u r n e l a v a l e u r t r a n s m i s e par l e e x i t ∗/ f p r i n t f ( stdout , " Je s u i s l e p e r e de p i d %d e t mon f i l s de p i d %d s e t e r m i n e a v e c l e getpid () , iReturn , WEXITSTATUS( s t a t u t ) ) ; } } f p r i n t f ( stdout , " Je s u i s l e p e r e de p i d %d e t j e me t e r m i n e \n" , getpid ( ) ) ; } return ( 0 ) ; } Exercice 6 : Recouvrement d’un processus,interpréteur Ecrire un interpréteur simple de commandes externes (exemples ps, ls, gcc, ...). #include #include #include #include < s t d i o . h> <e r r n o . h> <u n i s t d . h> < s t r i n g . h> void main ( i n t a r g c , char ∗ a r g v [ ] ) { pid_t p i d ; int i , statut , a ; char commande [ 1 0 ] ; s t r c p y ( commande , " " ) ; while ( strcmp ( commande , " e x i t " ) ! = 0 ) Université de Pau et des Pays de l’Adour st Licence Informatique Système d’exploitation { p r i n t f ( "$" ) ; fflush ( stdin ); s c a n f ( "%s " , commande ) ; pid = f o r k ( ) ; switch ( p i d ) { case −1: p e r r o r ( " e r r e u r de f o r k \n" ) ; e x i t ( −1); case 0 : p r i n t f ( "%s PPID = %d , PID = %d \n" , commande , getppid () , getpid ( ) ) ; i f ( strcmp ( commande , " e x i t " ) ! = 0 ) e x e c l p ( commande , commande , NULL ) ; perror (" execlp " ) ; // i l ne f a u t pas que l e f i l s c o n t i n u e e x i t ( −1); default : p i d = w a i t (& s t a t u t ) ; i f ( p i d==−1) per ro r ( " l e wait " ) ; else p r i n t f ( " p r o c e s s u s zombi %d\n" , p i d ) ; } } p r i n t f ( " \n \ t t o u t e s t t e r m i n e \n" ) ; } Université de Pau et des Pays de l’Adour