Ecole Nationale des Sciences de l’Informatique A. U. : 2014/2015
Systèmes d’exploitation & Programmation Concurrente II2
TP 1 - Gestion de Processus
=======================================================
Exercice 1 (2)
En utilisant le programme ci-dessous, identifiez les valeurs du pid aux lignes A, B, C, et D. (On assume que les pids du parent et du fils sont 2600 et 2603, respectivement.)
/\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\/
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
int main()
{
pid\_t pid, pid1;
/\ fork a child process \/
pid = fork ();
if (pid < 0) {/\ error occurred\/
fprintf( stderr, "Fork Failed");
return 1;
}
else if (pid==0) {/\ Child Process\/
pid1=getpid();
printf("child: pid = %d",pid); /\ A \/
printf("child: pid1 = %d",pid1); /\ B \/
}
else { /\ parent process \/
pid1 = getpid() ;
printf("parent: pid = %d",pid); /\ C \/
printf("parent: pid1 = %d" ,pid1); /\ D \/
wait(NULL);
}
return 0;
}
Réponse:
child: pid = 0child: pid1 = 1841parent: pid = 1841parent: pid1 = 1840
/\A\/ child: pid = 0 -- 0 Operation Fork réussie
/\B\/ child: pid1 = 1841 -- 2603 Identite du Fils
/\C\/ parent: pid = 1841 -- 2603 Identite du fils
/\D\/ parent: pid1 = 1840 -- 2600 Parent Id
Les deux processus (parent and child) continuent l’exécution à l’instruction qui suit le fork (), avec une seule différence: Le code de retour du fork() est zero pour le nouveau (fils) processus, pendant que l’identificateur du processus fils (nonzero) est retourné au processus parent.
/\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
Exercice 2 (5)
La suite de Fibonacci est une série de nombres 0, 1, 1, 2, 3, 5, 8, .... Elle est obtenue comme suit:
fib0 = 0
fib1 = 1
fibn = fibn-l + fibn-2
Ecrire un programme C qui utilise l’appel système fork() et qui permet de générer la suite de Fibonacci dans le processus fils. Le nombre de la suite sera fourni dans la ligne de commande. Exemple : si le nombre 5 est fourni, les 5 premiers nombres de la suite de Fibonacci seront donnés en output par le processus fils. Vu que les processus parent et fils ont leurs propres copies des données, le processus fils donnera la suite de nombres en output. Dans le programme, le processus parent doit invoquer l’appel wait () pour attendre la terminaison du processus fils avant de quitter (exit) le programme. Faites le contrôle d’erreur nécessaire pour assurer que le nombre passé en ligne de commande est non-négatif.
Solution:
Etapes à suivre :
Publicité
1. Créer un fichier « fibonacci.c » qui permet de générer/afficher une suite de Fibonacci d’ordre n (l’entier à entrer en Terminal).
/\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\Fichier fibonacci.c\\\\\\\\\\\\\\\\\\\\\*/
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
void main(int argc, char \* argv[] )
{
int a=0;
int b=1;
in t c;
int n=atoi(argv[1]);
while(n>0)
{
printf("%d \n",a);
c=a+b;
a=b;
b=c;
n=n-1;
}
}
/\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\/
1. Créer un fichier « tp1ex2.c » qui permet de créer un processus fils, exécuter fibonacci, etc.
/\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\Fichier tp1ex2.c\\\\\\\\\\\\\\\\\\\\\\\*/
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
void main(int argc, char \* argv[]) {
pid\_t pid;
int n=atoi(argv[1]);
if(argc != 2)
{
printf("Error \n");
}
if(n<0)
{
printf("Error:Negative Entry \n");
}
switch(pid=fork()) {
case -1:
perror("fork error \n");
break;
case 0:
execl("/home/Nessrine/fibonacci","fibonacci",argv[1],NULL);
break;
default:
wait(NULL);
break;
}
Publicité
/\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\/
1. Compiler
[Nessrine@localhost OSCPTP]$ gcc tp1ex2.c -o tp1ex2
[Nessrine@localhost OSCPTP]$ gcc fibonacci.c -o fibonacci
1. Exécuter
[Nessrine@localhost OSCPTP]$ ./tp1ex2 10
0
1
1
2
3
5
8
13
21
34
/\ FIN \/
/\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
Exercice 3 (2.5)
Déterminez combien de processus engendre l’exécution du programme C suivant et en donnez l’arborescence.
include < unistd .h>
int main ( void )
{
fork () && ( fork () || fork () );
sleep (2);
return 0; }
Réponse:
Le processus père engendre dans l’ensemble 3 autres processus. En effet, comme dans une instruction (a && b), b n’est évaluée que si l’ évaluation de a donne VRAI (c-à-d 1), de même, dans une instruction (a || b), b n’est évaluée que si l’évaluation de a donne FAUX (c-à-d 0),. Donc, dans (fork() && b) seulement le père exécute b, et dans (fork() || b) seulement le fils exécute b.
Soit pid1, pid2, et pid3 les valeurs retournées par les trois fork() respectivement.
On a si pid1=0, le fils F1 du processus principal n’a pas le droit d’exécuter (fork()|| fork () ) . D’où F1 n’a pas de fils. Par contre, pour pid1>0 (processus père), on peut exécuter (fork()|| fork () ) . Ainsi après avoir exécuté le premier fork() de cette expression, on obtient un deuxième fils, F2 du processus principal.
Si pid2>0 (processus principal=père de F2), on ne fait rien.
Si pid2=0 (au niveau de F2), on peut exécuter le troisième et dernier fork() qui donne un fils de F2, noté F3.
On obtient ainsi l’arborescence suivante :
Processus Principal
F1
F2
F3
/\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
Exercice 4 (6)
Soit le programme suivant :
#include <unistd.h>
#include <stdio.h>
int main ( ) {
int i=0 ;
while (fork() !=0 && i<2)
i=i+1;
printf(" Processus %d termine avec i=%d \n", getpid(), i);
return 0;
Publicité
}
Supposez que les appels à la fonction fork ne retournent pas d’erreur.
1. Donnez l’arborescence des processus engendrés par ce programme.
Processus Principal
F2
F3
F1
1. Donnez la valeur de i affichée par chacun des processus.
F1 (i=0), F2(i=1), F3(i=2) et PP(i=2)
1. Peut-on risquer d’engendrer un/des processus orphelin(s) et/ou zombie(s) ? si oui justifiez vos réponses et dire comment peut-on le vérifier ?
Oui, F2 peut terminer son exécution avant que PP ne termine. Ainsi F2 devient zombie. PP peut terminer son exécution avant que F3 ne termine. Ainsi F3 devient orphelin.
On peut vérifier ceci en exécutant ce programme et lançant la commande ps -la dans un autre terminal.
1. Modifiez le code de la fonction main de manière à
- éviter la présence éventuelle d’orphelins et zombies, et
- créer la nouvelle arborescence suivante, où PP est le processus principal :

Pour ceci, il suffit d’ajouter wait() dans la boucle while. Ainsi tout processus père sera obligé d’attendre la terminaison de ses processus fils. Quant à l’arborescence, on peut l’obtenir en remplaçant la condition sur le fork() par while(fork()≥0 && i<2) comme suit :
#include <unistd.h>
#include <stdio.h>
int main ( ) {
int i=0 ;
while (fork()≥0&& i<2){
i=i+1;
wait();
}
printf(" Processus %d termine avec i=%d \n", getpid(), i);
return 0;
}
Exercice 5 (4.5)
Partie I. Soit le programme C ci-dessous. (On suppose que toutes les fonctions retournent normalement, sans erreurs. On suppose également que tous les appels de printf() sont immédiatement flushed vers stdout).

Question: Pour chacune des combinaisons suivantes, Encerclez la bonne réponse (Oui) ou (Non) pour indiquer s’il est possible d’obtenir la combinaison comme output du programme ou pas.
A. 513242 Oui Non
B. 324251 Oui Non
C. 534212 Oui Non
D. 531422 Oui Non
E. 523142 Oui Non
Partie II. Soit le programme C ci-dessous. (On suppose que toutes les fonctions retournent normalement, sans erreurs. On suppose également que tous les appels de printf() sont immédiatement flushed vers stdout.).

Question: Enumérez tous les outputs possibles de ce programme.
Réponse:
Output 1 : 0123
Output 2 : 0132
Output 3 : 0312
Output 4 : 3012