Examen Système d'Exploitation 2023
Examen Système d'Exploitation 2023
1ère Année Master ISIL (2017/2018) Durée : 1h30 Documents non autorisés
Exercice 1 (3 pts) :
1. Qu’est-ce qu’un PCB et de quoi est-il composé ? (0,5 pt)
PCB est une structure de données particulière appelée bloc de contrôle de processus (PCB :
Process Control Bloc) et dont le rôle est de reconstituer le contexte du processus.
PCB est composé de l'ensemble des informations dynamiques qui représente l‘état d‘ exécution
d'un processus. Il contient aussi des informations sur l'ordonnancement du processus (priorité du
processus, les pointeurs sur les files d'attente)
2. L'appel système fork() est le moyen pour créer des processus, par duplication d'un processus
existant. Expliquer comment distinguer entre le processus père et le processus fils. (0,5 pt)
Pour distinguer le processus père du processus fils on regarde la valeur de retour de fork(), qui peut
être:
La valeur 0 dans le processus fils.
Positive pour le processus père et qui correspond au PID du processus fils.
Négative si la création de processus fils a échoué ;
3. Quelles critiques peut-on faire aux solutions de l'attente active et Peterson du problème de
l'exclusion mutuelle ?
On dira que deux tâches (instructions) ti et tj peuvent s’exécuter en parallèle si les conditions
suivantes sont satisfaites : (2pts)
a) R (ti) ∩ W (tj) =∅
b) W (ti) ∩ R (tj) =∅ t2 t1 t3
c) W(ti) ∩ W (tj) =∅
t5
t6
En se basant sur le graphe obtenu, réaliser la synchronisation des tâches (processus) en utilisant trois (03)
sémaphores S1, S2 et S3. (2pts)
Sémaphore S1=0, S2=0, S3=0
Pt1 (){ Pt2 (){ Pt3 (){ Pt4 (){ Pt5 (){ Pt6 (){
t1: b = b - d; t2: a = a + c; t3: e = e * f; P(S1); P(S1); P(S2);P(S2); P(S3);P(S3);
V(S1); V(S1); V(S3); V(S2); t4: b = b * a t5: b = b + e; t6: e = b / a;
} } } V(S2) V(S3) }
} }
Exercice 3 (7 pts) :
On considère le problème du producteur consommateur. Le processus producteur, délivre des
messages à un processus consommateur. Le producteur produit le message dans la ZoneP, puis le
dépose dans le buffer. Le consommateur prélève un message du buffer et le place dans la ZoneC où il
peut le consommer. Ce problème induit plusieurs types de contraintes de synchronisation qui sont:
1. Un producteur ne doit pas produire, ni déposer le message dans le buffer quand il n y a plus de
place pour déposer ce qu’il a produit.
2. Un consommateur ne doit pas prélever de messages quand le buffer est vide.
3. Producteurs et consommateurs ne doivent pas accéder en même temps au buffer.
- Écrire l'algorithme des processus producteurs et consommateurs en utilisant les sémaphores.
Semaphore Mutex = 1, Plein = 0, Vide=n ; Message tampon[];
Producteur (){ Consommateur (){
Message m ; Message m ;
Tantque Vrai faire Tantque vrai faire
P(Vide); P(Plein);
m = creermessage() ; P(Mutex);
P(Mutex) ; m = LectureTampon();
EcritureTampon(m); V(Mutex);
V(Mutex) ; V(Vide);
V(Plein); Fin Tantque
FinTantque }
}
Exercice 4 (4 pts) : Soit le programme ci-dessous :
1- Que fait le "processus 0" et le "processus 1" dans le code ci-dessus? Expliquez. (3pts)
1- Le processus 0 (le père) initialise un tableau aléatoirement, exécute l'appel système fork, calcule la
somme des éléments du tableau dans t[0], attend la terminaison de son fils et affiche t[0].
Le processus 1 (le fils) calcule le maximum du tableau dans t[0] qui il affiche.
2- Y a-t-il un risque pour que les deux processus fournissent des résultats incohérents ? Expliquez. (1pt)
Remarque : les processus s’annoncent à la fin du code avant le return 0
2 Non, car les deux processus ont des espace de données différents (pas de variable partagée)
Exercice 1 (5 pts) :
Dr. A. ABBAS 1
Examen système d’exploitation Département d’informatique, Université de Bouira
int main () {
pthread_t t1,t2;
for (int i=0;i<N;i++) pthread_join(t1, NULL);
t[i] = rand (); pthread_join(t2, NULL);
sem_init(&s, 0, 1); return 0;
pthread_create (&t1, NULL, A, NULL); }
pthread_create (&t2, NULL, B, NULL);
sem_t S; for(i=0;i<10;i++){
pthread_create(&Thread[i],NULL,&produit,NULL);
void * produit(){ }
int i,j,k,ligne; for(i=0;i<10;i++){
i=0; pthread_join(Thread[i],NULL);
while(i<taille){ }
sem_wait(&S); for(i=0;i<taille;i++){
while(T[i]!=-1 & i<taille){ for(j=0;j<taille;j++)
i++; printf("%.0f ",A[i][j]);
} printf("\n");
T[i]=1; }
ligne=i; return 0;
sem_post(&S); }
for(j=0;j<taille;j++)
for(k=0;k<taille;k++)
A[ligne][j]+=B[ligne][k]*C[k][j];
i++;
}
}
Dr. A. ABBAS 2
Département d’informatique, Université de Bouira
Examen système d’exploitation L3-SI Durée : 1h00
Exercice 1 (4 pts) :
1. Quelles sont les inconvénients des solutions de l'attente active et Peterson du problème de
l'exclusion mutuelle ?
2. Attente active : (2 pt)
3. 1- Cette méthode n'assure pas l'exclusion mutuelle
4. 2- Susceptible de consommer du temps en bouclant inutilement.
5. Peterson : (2 pt)
6. 1- La généralisation de cette solution aux cas de plusieurs processus est bien complexe.
7. 2- Susceptible de consommer du temps en bouclant inutilement.
Exercice 2 (5 pts) :
On cherche à évaluer l'expression suivante
e := ((b - d) * (a+ c) + (e*f)) / (a+c)
1. Réalise un découpage en tâches de cette expression sans l'ajout de variables intermédiaires. 1pt
t1: b = b - d
t2: a = a + c
t3: e = e * f
t4: b = b * a
t5: b = b + e
t6: e = b / a
2. En vous servant de la définition de la condition de Bernstein, donner le graphe de précédence
correspondant. 2 pt
t1: R(t1) = {d}, W(t1) ={ b};
t2: R(t2) ={ c}, W(t2) = {a};
t3: R(t3) = { f}, W(t3) ={ e}
t4: R(t4) ={ a}, W(t4) = {b};
t5: R(t5) ={e}, W(t5) = {b};
t6: R(t6) ={b, a}, W(t6) = {e}
On dira que deux tâches (instructions) ti et tj peuvent s’exécuter en parallèle si les conditions
suivantes sont satisfaites :
a) R (ti) ∩ W (tj) =∅
b) W (ti) ∩ R (tj) =∅
c) W(ti) ∩ W (tj) =∅
t1 // t2
t1 // t3
t1 → t4 : t1 précéde t4 puisque le b de t4 est celui calculé par t1
t1 t5 : t1 ne précéde pas t5 puisque le b de t5 (W(t1) ∩ W (t5)= {b}) ce n'est pas celui calculé par t1
mais c'est celui de t4
t1 t6 : même chose t2 t1 t3
t2 // t3
t2 → t4
t2 // t5 t4 t4 → t5
t2→ t6 t4 t6
t3 // t4 t5
t3 → t5 t5 → t6
t3 t6 t6
Dr. A. ABBAS 1
Département d’informatique, Université de Bouira
Examen système d’exploitation L3-SI Durée : 1h00
3. En se basant sur le graphe obtenu, réaliser la synchronisation des tâches (processus) en utilisant trois (03)
sémaphores S1, S2 et S3. 2pts
Sémaphore S1=0, S2=0, S3=0
Pt1 (){ Pt2 (){ Pt3 (){ Pt4 (){ Pt5 (){ Pt6 (){
t1: b = b - d; t2: a = a + c; t3: e = e * f; P(S1); P(S1); P(S2);P(S2); P(S3);P(S3);
V(S1); V(S1); V(S3); V(S2); t4: b = b * a t5: b = b + e; t6: e = b / a;
} } } V(S2) V(S3)
} }
Exercice 3 (6 pts) :
Soit une route reliant la ville A et la ville B. Les règles de circulation sur cette route sont les suivantes:
1. Des voitures peuvent y circuler ensemble dans le sens A → B ou dans le sens B → A
(circulation alternée),
2. La route ne doit jamais être empruntée simultanément par deux voitures allant en sens inverse.
3. La priorité d'accès à la route est la même pour les deux sens.
On considère donc deux classes d’utilisateurs (processus) : voitures de A vers B (V_AB) et voitures de
B vers A (V_BA).
Question:
En utilisant les sémaphores, écrivez les algorithmes des fonctions de demande d’accès aux tronçons
acces_AB(), acces_BA() et des fonctions de sortie des tronçons AB_sort () et BA_sort() de façon à ce
que les processus V-AB et V-BA respectent les trois règles de circulation sur la route. Précisez
clairement vos déclarations et initialisations.
Solution:
Initialisation 2pts
int nbAB=0; //Compte le nombre de voitures allant de A vers B
int nbBA =0; entier (init à 0) Compte le nombre de voitures allant de B vers A
Sempahore route=1; // pour permettre que des voitures de sens contraire ne s'engagent pas dans la voie en
même temps.
Sempahore mutexAB=1;//pour protéger la mise à jour en exclusion mutuelle de la variable protégée nbAB
Sempahore mutexBA=1; //pour protéger la mise à jour en exclusion mutuelle de la variable protégée nbBA
Code des fonctions 1pt/fonction
Fonction acces_AB() { Fonction acces_BA () {
P(mutexAB); P(mutexBA);
nbAB++; nbAB++;
si (nbAB == 1) P(route); si (nbAB == 1) P(route);
V(mutexAB);} V(mutexBA);}
Fonction AB_sort () Fonction BA_sort () {
P(mutexAB); (mutexBA);
nbAB--; nbBA--;
si (nbAB == 0) V(route); si (nbBA == 0) V(route);
P(mutexAB);} (mutexBA);}
Exercice 4 (5 pts) :
Écrire un programme qui crée 5 processus fils, chaque fils affiche son PID et se termine. Le père devra
attendre la fin de ses 5 fils et afficher quel a été le premier et dernier processus qui a terminé.
#include <stdio.h>
#include <stdlib.h>
Dr. A. ABBAS 2
Examen système d’exploitation Département d’informatique, Université de Bouira
#include <sys/types.h>
#include <unistd.h>
int main(){
pid_t pid_premier, pid_dernier;
int i,pid[5],status;
for(i=0;i<5;i++){
pid[i]=fork();
if (pid[i] == -1) {
// ERREUR
fprintf(stderr, "Impossible de créer un fils (%d)\n", i);
} else if (pid[i]==0) {
// FILS
printf("Fils %2d (PID=%d): Activé\n", i, getpid());
exit(0);
} else {
printf("Père : Activation du fils %2d\n", i);
}
}
pid_premier = wait(&status);
wait(&status);
wait(&status);
wait(&status);
pid_dernier = wait(&status);
printf("Premier processus a finir : %d\n", pid_premier);
printf("Dernier processus a finir : %d\n", pid_dernier);
return 0;
}
On dira que deux tâches (instructions) ti et tj peuvent s’exécuter en parallèle si les conditions
suivantes sont satisfaites :
a) R (ti) W (tj) =
b) W (ti) R (tj) =
c) W(ti) W (tj) =
t1 // t2
t1 // t3
t1 → t4 : t1 précéde t4 puisque le b de t4 est celui calculé par t1
t1 t5 : t1 ne précéde pas t5 puisque le b de t5 (W(t1) W (t5)= {b}) ce n'est pas celui calculé
par t1 mais celui de t4
t1 t6 : même chose
t2 // t3
t2 → t4 t2 t1 t3
t4 → t5
t2 // t5
t4 t6
t2→ t6
t4
t5 → t6
t3 // t4
t5
t3 → t5
t3 t6 t6
Dr. A. ABBAS 1
Département d’informatique, Université de Bouira
Examen système d’exploitation L3 SI (2018/2019) Durée : 1h30
3. En se basant sur le graphe obtenu, réaliser la synchronisation des tâches (processus) en utilisant trois
(03) sémaphores S1, S2 et S3. 3pts
Sémaphore S1=0, S2=0, S3=0
Pt1 (){ Pt2 (){ Pt3 (){ Pt4 (){ Pt5 (){ Pt6 (){
t1: b = b - d; t2: a = a + c; t3: e = e * f; P(S1); P(S1); P(S2);P(S2); P(S3);P(S3);
V(S1); V(S1); V(S3); V(S2); t4: b = b * a t5: b = b + e; t6: e = b / a;
} } } V(S2) V(S3) }
} }
Exercice 3 (8 pts) : On considère une route reliant la ville de Bouira et la station de Tikjda. Les règles
de circulation sur cette route sont les suivantes:
Des voitures peuvent y circuler ensemble dans le sens Bouira → Tikjda ou dans le sens Tikjda
→ Bouira (circulation alternée),
La route ne doit jamais être empruntée simultanément par deux voitures allant en sens inverse.
La priorité d'accès à la route est la même pour les deux sens.
On considère donc deux classe d’utilisateurs : voitures de Bouira vers Tikjda (V-BT) et voitures de
Tikjda vers Bouira V-TB.
Question:
1. Quelle est la différence entre ce problème et le modèle de lecteurs/rédacteurs ? 1,5 pt
La différence est que dans le modèle lecteur/rédacteur
on autorise qu’un seul rédacteur à la fois en train d’occuper la ressource partagée (fichier) alors que
dans ce problème, la ressource (la route) peut être occupée par plusieurs processus en même temps et ceci
pour les deux classes V-BT et V-TB. 1pt
le lecteur ne peut pas commencé à lire si aucun rédacteur n'à déjà rédiger alors dans ce problème la
route est autorisée d'accès initialement pour le processus des deux classes V-BT et V-TB 0.5pt
2. En utilisant les sémaphores, écrivez les algorithmes des fonctions de demande d’accès aux
tronçons BTaccses () "Bouira vers Tikjda", TBaccses () "Tikjda vers Bouira" et des fonctions de
sortie des tronçons TBexit () et BTexit () de façon à ce que les processus V-BT et V-TB
respectent les règles de circulation sur la route. Précisez clairement vos déclarations et
initialisations.
Solution:
Initialisation 2,5
int nbTB=0; //Compte le nombre de voitures allant de Tikjda vers Bouira
int nbBT =0; entier (init à 0) Compte le nombre de voitures allant de Bouira vers Tikjda
Sempahore route=1; // pour permettre que des voitures de sens contraire ne s'engagent pas dans la
voie en même temps.
Sempahore mutexTB=1;//pour protéger la mise à jour en exclusion mutuelle de la variable protégée
nbTB
Sempahore mutexBT=1; //pour protéger la mise à jour en exclusion mutuelle de la variable protégée
nbBT
Code des fonctions 1pt/fonction
Dr. A. ABBAS 2
Département d’informatique, Université de Bouira
Examen système d’exploitation L3 SI (2018/2019) Durée : 1h30
Exercice 4 (4 pts) : Soit le programme ci-dessous :
# define N 100 for (i=0;i<N;i++) else {
int k = 0; t[i] = rand (); for(i=1;i<N;i++)
int main () { P = fork (); t [0]+= t[i];
float t[N]; if (P ==0) { waitpid (P ,NULL ,0);
int i; k=1; }
pid_t P for(i=0 ; i<N ; i++) printf ("processus%d, %f \n",k, t[0]);
if (t[0] < t[i]) return 0;
t[0]= t[i]; }
}
1- Que fait le "processus 0" et le "processus 1" dans le code ci-dessus? Expliquez. (3pts)
a- Le processus 0 (le père) 1
initialise un tableau aléatoirement,
exécute l'appel système fork,
calcule la somme des éléments du tableau dans t[0],
attend la terminaison de son fils
affiche t[0].
b- Le processus 1 (le fils) 1
calcule le maximum du tableau dans t[0]
affiche t[0].
2- Y a-t-il un risque pour que les deux processus fournissent des résultats incohérents ? Expliquez. (1pt)
Non, car les deux processus ont des espace de données différents (pas de variable partagée)
Remarque : les processus s’annoncent à la fin du code avant le return 0
Dr. A. ABBAS 3
Corrigé examen système d’exploitation Département d’informatique
Exercice 1 (7 pts) :
On cherche à évaluer l'expression suivante :
c := ((a-c) + (e*f) / (a-c)) / ((a-c) * (a+c))
1. Réalise un découpage en tâches de cette expression. 2pts
t7
Corrigé examen système d’exploitation Département d’informatique
# define N 100
int k = 0; if (P ==0) { else {
int main () { k=1; for(i=1;i<N;i++)
float t[N]; for(i=0 ; i<N ; i++) t [0]+= t[i];
int i; if (t[0] < t[i]) waitpid (P ,NULL ,0);
pid_t P t[0]= t[i]; }
} printf ("processus%d, %f \n",k, t[0]);
for (i=0;i<N;i++) return 0;
t[i] = rand (); }
P = fork ();
1- Que fait le "processus 0" et le "processus 1" dans le code ci-dessus? Expliquez.
1- Le processus 0 (le père) 3pts
initialise un tableau aléatoirement,
exécute l'appel système fork,
calcule la somme des éléments du tableau dans t[0],
attend la terminaison de son fils et
affiche t[0].
Le processus 1 (le fils) 1 pts
calcule le maximum du tableau dans t[0]
qui il affiche.
Exercice 3 (6 pts) :
Écrire un programme qui crée 10 processus fils, chaque fils affiche son PID et le PID de son
père et se termine. Le père devra attendre la fin de ses 5 fils et afficher quel a été le premier et
le deuxième processus qui a terminé.
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int main(){
pid_t pid_premier, pid_ deux;
int i,pid[10],status;
for(i=0;i<10;i++) {
pid[i]=fork();
if (pid[i]==0) {// FILS
printf("Fils (PID=%d): du père (PID%d)\n", getpid(), getppid());
exit(0);// ce n'est pas break
}
}
pid_premier = wait(&status);
pid_deux = wait(&status);
wait(&status); wait(&status); wait(&status);
printf("Premier processus a finir : %d\n", pid_premier);
printf("Deuxième processus a finir : %d\n", pid_ deux);
return 0;
}
Corrigé examen système d’exploitation Département d’informatique
Exercice 1 (7 pts) :
On cherche à évaluer l'expression suivante :
c := ((a-c) + (e*f) / (a-c)) / ((a-c) * (a+c))
1. Réalise un découpage en tâches de cette expression. 2pts
t7
Corrigé examen système d’exploitation Département d’informatique
# define N 100
int k = 0; if (P ==0) { else {
int main () { k=1; for(i=1;i<N;i++)
float t[N]; for(i=0 ; i<N ; i++) t [0]+= t[i];
int i; if (t[0] < t[i]) waitpid (P ,NULL ,0);
pid_t P t[0]= t[i]; }
} printf ("processus%d, %f \n",k, t[0]);
for (i=0;i<N;i++) return 0;
t[i] = rand (); }
P = fork ();
1- Que fait le "processus 0" et le "processus 1" dans le code ci-dessus? Expliquez.
1- Le processus 0 (le père) 3pts
initialise un tableau aléatoirement,
exécute l'appel système fork,
calcule la somme des éléments du tableau dans t[0],
attend la terminaison de son fils et
affiche t[0].
Le processus 1 (le fils) 1 pts
calcule le maximum du tableau dans t[0]
qui il affiche.
Exercice 3 (6 pts) :
Écrire un programme qui crée 10 processus fils, chaque fils affiche son PID et le PID de son
père et se termine. Le père devra attendre la fin de ses 5 fils et afficher quel a été le premier et
le deuxième processus qui a terminé.
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int main(){
pid_t pid_premier, pid_ deux;
int i,pid[10],status;
for(i=0;i<10;i++) {
pid[i]=fork();
if (pid[i]==0) {// FILS
printf("Fils (PID=%d): du père (PID%d)\n", getpid(), getppid());
exit(0);// ce n'est pas break
}
}
pid_premier = wait(&status);
pid_deux = wait(&status);
wait(&status); wait(&status); wait(&status);
printf("Premier processus a finir : %d\n", pid_premier);
printf("Deuxième processus a finir : %d\n", pid_ deux);
return 0;
}
Département d’informatique, Université de Bouira
Exercice 1 (2 pts) :
1. Quelles sont les opérations d'un sémaphore qui s’exécutent d’une manière indivisible ?
Le test de la valeur du sémaphore, le changement de sa valeur et la mise en attente éventuelle
sont effectués en une seule opération atomique indivisible. C'est-à-dire les opérations P(S) et
V(S). 1pts
2. L'appel système fork() est le moyen pour créer des processus, par duplication d'un processus existant.
Expliquer comment distinguer entre le processus père et le processus fils.
Pour distinguer le processus père du processus fils on regarde la valeur de retour de fork(), qui
peut être:1pts
La valeur 0 dans le processus fils.
Positive pour le processus père et qui correspond au PID du processus fils
Négative si la création de processus a échoué ;
1- Synchroniser les deux processus à l'aide des sémaphores afin de montrer à l'écran la sortie suivante:
je suis le processus 2
je suis le processus 1
je suis le processus 1
je suis le processus 2
sem_t s1, s2
sem_init(s1,0,2) ; /*pour permettre au processus P2 de commencer*/ 0.5pt
sem_init(s2,0,0) /*pour empêcher le processus P1 de commencer jusqu’à ce que P2 le réveil */ 0.5pt
P1( ) { P2 ( ) {
While (TRUE){ While (TRUE){
sim_wait(&s2) ; // (0,5 pt) sim_wait(&s1) ;sim_wait(&s1); (1 pt)
printf("je suis le processus 2\n"); ; printf("je suis le processus 2\n"); ;
sim_post(&s1) ; // (0,5 pt) sim_post(&s2); sim_post(&s2) ; (1 pt)
} }
} }
Exercice 3 (5 pts) ::
Écrire un programme utilisant 3 threads afin d'afficher la séquence suivante:
A, B,C, A,B, C...,
Où, le thread 1 affiche la lettre A, le thread 2 affiche la lettre B et le thread 3 affiche la lettre C
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
sem_t sem1, sem2, sem3;
void *f1(){ void *f2(){ void *f3(){
while(1){ while(1) { while(1) {
sem_wait(&sem1); sem_wait(&sem2); sem_wait(&sem3);
printf("A, "); printf("B, "); printf("C, ");
sem_post(&sem2); sem_post(&sem3); sem_post(&sem1);
} } }
} } }
int main(){
pthread_t p1, p2, p3;
sem_init(&sem1, 0, 1);
sem_init(&sem2, 0, 0);
sem_init(&sem3, 0, 0);
pthread_create(&p1, NULL, f1, (void*)NULL);
pthread_create(&p2, NULL, f2, (void*)NULL);
pthread_create(&p3, NULL, f3, (void*)NULL);
pthread_join(p1, NULL);
pthread_join(p2, NULL);
pthread_join(p3, NULL);
return 0;
}
Exercice4 (5 pts) :
Écrire un programme en C qui :
Initialise un tableau aléatoirement,
Crée un processus fils,
Calcule la somme des éléments du tableau dans une variable S,
Attend la terminaison de son fils et affiche S.
Le processus fils calcule et affiche le maximum du tableau.
# define N 100
int main () { if (P == 0) { else {
float t[N], S=0,max=0; for(i=0 ; i<N ; i++) for(i=1; i<N; i++)
int i; if (max < t[i]) S+= t[i];
pid_t P max= t[i]; waitpid (P ,NULL ,0);
for (i=0; i < N; i++) printf ("Max=%f \n", max); printf ("S=%f \n", S);
t[i] = rand (); } }
P = fork (); return 0;
}
A. ABBAS 2
Département d’informatique, Université de Bouira
L3 SI (2023/2024) Durée : 1h30
ExamEn : SyStèmE d’Exploitation 2
Exercice 1 (3 pts) :
1. Dans quel(s) état(s) peut se retrouver un processus juste après son exécution ?
prêt, bloqué ou terminer
2. Citez quatre (4) mécanismes qui permettent de contrôler les accès aux données partagées.
Les mécanismes sont : mécanisme d'attente active, peterson, les sémaphores et
moniteur.
Question:
En utilisant les numéros de lignes dans le code, tracer la séquence d'exécution d'instruction, sous
forme du tableau donné ci-après. Montrer les valeurs de x et y à la fin de chaque instruction.
Appel de la procédure Numéro de lignes (i) Valeur de X Valeur de Y
du moniteur
... ... ... ...
Département d’informatique, Université de Bouira
L3 SI (2023/2024) Durée : 1h30
ExamEn : SyStèmE d’Exploitation 2
1ère Année Master ISIL (2017/2018) Durée : 1h30 Documents non autorisés
Exercice 1 (3 pts) :
1. Qu’est-ce qu’un PCB et de quoi est-il composé ? (0,5 pt)
PCB est une structure de données particulière appelée bloc de contrôle de processus (PCB :
Process Control Bloc) et dont le rôle est de reconstituer le contexte du processus.
PCB est composé de l'ensemble des informations dynamiques qui représente l‘état d‘ exécution
d'un processus. Il contient aussi des informations sur l'ordonnancement du processus (priorité du
processus, les pointeurs sur les files d'attente)
2. L'appel système fork() est le moyen pour créer des processus, par duplication d'un processus
existant. Expliquer comment distinguer entre le processus père et le processus fils. (0,5 pt)
Pour distinguer le processus père du processus fils on regarde la valeur de retour de fork(), qui peut
être:
La valeur 0 dans le processus fils.
Positive pour le processus père et qui correspond au PID du processus fils.
Négative si la création de processus fils a échoué ;
3. Quelles critiques peut-on faire aux solutions de l'attente active et Peterson du problème de
l'exclusion mutuelle ?
On dira que deux tâches (instructions) ti et tj peuvent s’exécuter en parallèle si les conditions
suivantes sont satisfaites : (2pts)
a) R (ti) ∩ W (tj) =∅
b) W (ti) ∩ R (tj) =∅ t2 t1 t3
c) W(ti) ∩ W (tj) =∅
t5
t6
En se basant sur le graphe obtenu, réaliser la synchronisation des tâches (processus) en utilisant trois (03)
sémaphores S1, S2 et S3. (2pts)
Sémaphore S1=0, S2=0, S3=0
Pt1 (){ Pt2 (){ Pt3 (){ Pt4 (){ Pt5 (){ Pt6 (){
t1: b = b - d; t2: a = a + c; t3: e = e * f; P(S1); P(S1); P(S2);P(S2); P(S3);P(S3);
V(S1); V(S1); V(S3); V(S2); t4: b = b * a t5: b = b + e; t6: e = b / a;
} } } V(S2) V(S3) }
} }
Exercice 3 (7 pts) :
On considère le problème du producteur consommateur. Le processus producteur, délivre des
messages à un processus consommateur. Le producteur produit le message dans la ZoneP, puis le
dépose dans le buffer. Le consommateur prélève un message du buffer et le place dans la ZoneC où il
peut le consommer. Ce problème induit plusieurs types de contraintes de synchronisation qui sont:
1. Un producteur ne doit pas produire, ni déposer le message dans le buffer quand il n y a plus de
place pour déposer ce qu’il a produit.
2. Un consommateur ne doit pas prélever de messages quand le buffer est vide.
3. Producteurs et consommateurs ne doivent pas accéder en même temps au buffer.
- Écrire l'algorithme des processus producteurs et consommateurs en utilisant les sémaphores.
Semaphore Mutex = 1, Plein = 0, Vide=n ; Message tampon[];
Producteur (){ Consommateur (){
Message m ; Message m ;
Tantque Vrai faire Tantque vrai faire
P(Vide); P(Plein);
m = creermessage() ; P(Mutex);
P(Mutex) ; m = LectureTampon();
EcritureTampon(m); V(Mutex);
V(Mutex) ; V(Vide);
V(Plein); Fin Tantque
FinTantque }
}
Exercice 4 (4 pts) : Soit le programme ci-dessous :
1- Que fait le "processus 0" et le "processus 1" dans le code ci-dessus? Expliquez. (3pts)
1- Le processus 0 (le père) initialise un tableau aléatoirement, exécute l'appel système fork, calcule la
somme des éléments du tableau dans t[0], attend la terminaison de son fils et affiche t[0].
Le processus 1 (le fils) calcule le maximum du tableau dans t[0] qui il affiche.
2- Y a-t-il un risque pour que les deux processus fournissent des résultats incohérents ? Expliquez. (1pt)
Remarque : les processus s’annoncent à la fin du code avant le return 0
2 Non, car les deux processus ont des espace de données différents (pas de variable partagée)
On dira que deux tâches (instructions) ti et tj peuvent s’exécuter en parallèle si les conditions
suivantes sont satisfaites :
a) R (ti) ∩ W (tj) =∅
b) W (ti) ∩ R (tj) =∅
c) W(ti) ∩ W (tj) =∅
t1 // t2
t1 // t3
t1 → t4 : t1 précéde t4 puisque le b de t4 est celui calculé par t1
t1 t5 : t1 ne précéde pas t5 puisque le b de t5 (W(t1) ∩ W (t5)= {b}) ce n'est pas celui calculé par t1
mais c'est celui de t4
t1 t6 : même chose t2 t1 t3
t2 // t3
t2 → t4
t2 // t5 t4 t4 → t5
t2→ t6 t4 t6
t3 // t4 t5
t3 → t5 t5 → t6
t3 t6 t6
Dr. A. ABBAS 1
Département d’informatique, Université de Bouira
Examen système d’exploitation L3-SI Durée : 1h00
3. En se basant sur le graphe obtenu, réaliser la synchronisation des tâches (processus) en utilisant trois (03)
sémaphores S1, S2 et S3. 2pts
Sémaphore S1=0, S2=0, S3=0
Pt1 (){ Pt2 (){ Pt3 (){ Pt4 (){ Pt5 (){ Pt6 (){
t1: b = b - d; t2: a = a + c; t3: e = e * f; P(S1); P(S1); P(S2);P(S2); P(S3);P(S3);
V(S1); V(S1); V(S3); V(S2); t4: b = b * a t5: b = b + e; t6: e = b / a;
} } } V(S2) V(S3)
} }
Exercice 3 (6 pts) :
Soit une route reliant la ville A et la ville B. Les règles de circulation sur cette route sont les suivantes:
1. Des voitures peuvent y circuler ensemble dans le sens A → B ou dans le sens B → A
(circulation alternée),
2. La route ne doit jamais être empruntée simultanément par deux voitures allant en sens inverse.
3. La priorité d'accès à la route est la même pour les deux sens.
On considère donc deux classes d’utilisateurs (processus) : voitures de A vers B (V_AB) et voitures de
B vers A (V_BA).
Question:
En utilisant les sémaphores, écrivez les algorithmes des fonctions de demande d’accès aux tronçons
acces_AB(), acces_BA() et des fonctions de sortie des tronçons AB_sort () et BA_sort() de façon à ce
que les processus V-AB et V-BA respectent les trois règles de circulation sur la route. Précisez
clairement vos déclarations et initialisations.
Solution:
Initialisation 2pts
int nbAB=0; //Compte le nombre de voitures allant de A vers B
int nbBA =0; entier (init à 0) Compte le nombre de voitures allant de B vers A
Sempahore route=1; // pour permettre que des voitures de sens contraire ne s'engagent pas dans la voie en
même temps.
Sempahore mutexAB=1;//pour protéger la mise à jour en exclusion mutuelle de la variable protégée nbAB
Sempahore mutexBA=1; //pour protéger la mise à jour en exclusion mutuelle de la variable protégée nbBA
Code des fonctions 1pt/fonction
Fonction acces_AB() { Fonction acces_BA () {
P(mutexAB); P(mutexBA);
nbAB++; nbAB++;
si (nbAB == 1) P(route); si (nbAB == 1) P(route);
V(mutexAB);} V(mutexBA);}
Fonction AB_sort () Fonction BA_sort () {
P(mutexAB); (mutexBA);
nbAB--; nbBA--;
si (nbAB == 0) V(route); si (nbBA == 0) V(route);
P(mutexAB);} (mutexBA);}
Exercice 4 (5 pts) :
Écrire un programme qui crée 5 processus fils, chaque fils affiche son PID et se termine. Le père devra
attendre la fin de ses 5 fils et afficher quel a été le premier et dernier processus qui a terminé.
#include <stdio.h>
#include <stdlib.h>
Dr. A. ABBAS 2
Examen système d’exploitation Département d’informatique, Université de Bouira
#include <sys/types.h>
#include <unistd.h>
int main(){
pid_t pid_premier, pid_dernier;
int i,pid[5],status;
for(i=0;i<5;i++){
pid[i]=fork();
if (pid[i] == -1) {
// ERREUR
fprintf(stderr, "Impossible de créer un fils (%d)\n", i);
} else if (pid[i]==0) {
// FILS
printf("Fils %2d (PID=%d): Activé\n", i, getpid());
exit(0);
} else {
printf("Père : Activation du fils %2d\n", i);
}
}
pid_premier = wait(&status);
wait(&status);
wait(&status);
wait(&status);
pid_dernier = wait(&status);
printf("Premier processus a finir : %d\n", pid_premier);
printf("Dernier processus a finir : %d\n", pid_dernier);
return 0;
}
Exercice 2 (8 pts) : Soit le programme suivant de synchronisation de deux threads avec l'utilisation de
sémaphores.
#include <stdio.h> void *thread2 (void * arg){
#include <stdlib.h> while(1) {
#include <pthread.h> sem_wait(&my_sem2); //(0.5 pt)
#include <semaphore.h> printf ("Je suis thread2,");
sem_t *my_sem1, *my_sem2; //(1 pt) sem_post(&my_sem1); //(0.5 pt)
}}
void *thread1 (void * arg) { void main (int ac, char **av){
while(1) { pthread_t *th1, *th2;
sem_wait(&my_sem1); // (0.5 pt) sem_init(&my_sem1, 0 ,1); //(0.5 pt)
printf ("Je suis thread1,"); sem_init(&my_sem2, 0 ,0); //(0.5 pt)
sem_post(&my_sem2); //(0.5 pt) pthread_create(&th1, NULL,&thread1, NULL) ;
} } pthread_create(&th2, NULL,&thread2, NULL) ;
pthread_join(th1, NULL);
pthread_join(th2, NULL);
printf ("Je suis main,");
}
Question :
1. Complétez ce programme pour qu'il affiche la séquence suivante : Je suis thread1, Je suis thread2,
Je suis thread1, Je suis thread2,....
2. Utiliser le programme précédent pour écrire un autre programme qui initialise une variable entière
cpt à 1 et qui crée deux threads p1 et p2. Le thread p1 incrémente cpt 10000 fois et le thread p2
décrémente cpt 10000 fois. Utiliser un sémaphore pour résoudre le problème de l’accès concurrent à
la variable cpt.
#include <stdio.h> void* p2(void* arg){
#include <stdlib.h> int i=0;
#include <unistd.h> while (i<10000){
#include <pthread.h> sem_wait(&semaphore); (0.5 pt)
#include <semaphore.h> cpt -=1;
sem_t semaphore; (1 pt) sem_post(&semaphore); (0.5 pt)
int cpt =1; i++;
}
void* p1(void* arg){ }
int i=0; int main(void) {
while (i<10000){ pthread_t tache1, tache2;
sem_wait(&semaphore); (0.5 pt) sem_init(&semaphore, 0, 1); (1 pt)
cpt +=1; pthread_create (&tache1, NULL, &p1, NULL);
sem_post(&semaphore); (0.5 pt) pthread_create (&tache2, NULL, &p2, NULL);
i++; pthread_join(tache1, NULL);
} pthread_join(tache2, NULL);
} printf("cpt =%d:\n", cpt );
return 0;
}
Université de Bouira
Département d’informatique 3ième Année SI (2020/2021)
Module : système d'exploitation Durée : 1h
Examen Système d'exploitation
Exercice 3 (7 pts) :
On considère le problème du producteur consommateur. Le processus producteur, délivre des
messages à un processus consommateur. Le producteur produit le message dans la ZoneP, puis le
dépose dans le buffer. Le consommateur prélève un message du Buffer et le place dans la ZoneC où il
peut le consommer. Ce problème introduit plusieurs types de contraintes de synchronisation:
1. Un producteur ne doit pas déposer dans le buffer quand il n y a plus de place pour déposer ce qu’il a
produit.
2. Un consommateur ne doit pas prélever de messages quand le buffer est vide.
3. Producteurs et consommateurs ne doivent pas accéder en même temps au buffer.
Question :
Écrire l'algorithme des processus producteurs et consommateurs en utilisant les sémaphores.
Semaphore Mutex = 1, Plein = 0, Vide=n ; (2 pt)
Message tampon[];
Producteur ( ){ Consommateur( ) {
Message m ; Message m ;
Tantque Vrai faire Tantque Vrai faire
P(Vide); (1 pt) P(Plein); (1 pt)
m = creermessage() ; P(Mutex) ; (0.5 pt)
P(Mutex) ; (0.5 pt) m = LectureTampon();
EcritureTampon(m); V(Mutex) ; (0.5 pt)
V(Mutex) ; (0.5 pt) V(Vide); (1 pt)
V(Plein); (1 pt) Fin Tantque
FinTantque } }
Test
C D
A
B
E
- Réaliser la synchronisation de ces processus en utilisant les sémaphores.
Sémaphore S1=0, S2=0;S3=0
Exo1: Expliquez pas-à-pas comment s'exécute le programme suivant et donner le résultat d'affichage. (8 pts)
1. main () {
2. int y ;
3. y=0 ;
4. pid_t thr ;
5. thr =fork() ;
6. if (thr ==0) {
7. y=5 ;
8. prinf(‘‘y=%d\n’’, y) ;
9. } else
10. prinf(‘‘y=%d\n’’, y) ;
11. }
inst2et3: déclaration d'une varaible y de type int et affectation de 0
inst4: déclaration d'une varaible thr de type pid_t
inst5: création du processus fils suite à l'appel de la fonction fork() et affectation de la
valeur de retour à la variable thr
inst6: test la valeur de thr, si elle égale à 0 alors on est dans le fils
inst7: le processus fils affecte 5 à y
inst8: le processus fils affiche: y=5
inst9: si la valeur de thr différente de 0 alors on est dans le père
inst10: le processus père affiche: y=0
A. ABBAS 3 Bon
courage
Université de Bouira
Département d’informatique 3ième Année SI (2020/2021)
Module : système d'exploitation Durée : 1h
Exercice 2 (8 pts) : Soit le programme suivant de synchronisation de deux threads avec l'utilisation de
sémaphores.
#include <stdio.h> void *thread2 (void * arg){
#include <stdlib.h> while (1) {
#include <pthread.h>
#include <semaphore.h> printf ("Je suis thread2,");
............................. my_sem; }
}
void *thread1 (void * arg) { void main (int ac, char **av){
while (1) { pthread_t th1, th2;
sem_init (&my_sem, ...... , ......);
printf ("Je suis thread1,"); pthread_create (..............., NULL, ........., NULL) ;
pthread_create (................, NULL, ........., NULL) ;
} pthread_join (................, NULL);
} pthread_join (................, NULL);
}
Question :
1. Complétez ce programme pour qu'il affiche la séquence suivante : Je suis thread1, Je suis thread2,
Je suis thread1, Je suis thread2,....
2. Utiliser le programme précédent pour écrire un autre programme qui initialise une variable entière
cpt à 1 et qui crée deux threads p1 et p2. Le thread p1 incrémente cpt 10000 fois et le thread p2
décrémente cpt 10000 fois. Utiliser un sémaphore pour résoudre le problème de l’accès concurrent à
la variable cpt.
Exercice 3 (7 pts) :
On considère le problème du producteur consommateur. Le processus producteur, délivre des
messages à un processus consommateur. Le producteur produit le message dans la ZoneP, puis le
dépose dans le buffer. Le consommateur prélève un message du Buffer et le place dans la ZoneC où il
peut le consommer. Ce problème introduit plusieurs types de contraintes de synchronisation:
1. Un producteur ne doit pas déposer dans le buffer quand il n y a plus de place pour déposer ce qu’il a
produit.
2. Un consommateur ne doit pas prélever de messages quand le buffer est vide.
3. Producteurs et consommateurs ne doivent pas accéder en même temps au buffer.
Question :
Écrire l'algorithme des processus producteurs et consommateurs en utilisant les sémaphores.
C D
A
B
E
- Réaliser la synchronisation de ces processus en utilisant les sémaphores.
Exo1: Expliquez pas-à-pas comment s'exécute le programme suivant et donner le résultat d'affichage. (8 pts)
1. main () {
2. int y ;
3. y=0 ;
4. pid_t thr ;
5. thr =fork() ;
6. if (thr ==0) {
7. y=5 ;
8. prinf(‘‘y=%d\n’’, y) ;
9. } else
10. prinf(‘‘y=%d\n’’, y) ;
11. }
Exercice 1 (4 pts) :
Exercice 2 (6 pts) :
Soit le schéma suivant décrivant les transitions d’un processus. Précisez dans le tableau ci-dessous à quoi
correspondent les transitions numérotées par 1, 2, 3, 4 et précisez quels sont les événements qui
provoquent chacune de ces transitions.
Nouveau Fin
1
Prêt En exécution
2
4 3
Bloqué
Exercice 3 (5 pts):
Considérons un objet (une base de données par exemple) qui n'est accessible que par deux catégories
d'opérations : les lectures et les écritures. Plusieurs lectures (consultations) peuvent avoir lieu
simultanément ; par contre les écritures (mises à jour) doivent se faire en exclusion mutuelle. Ce
problème induit plusieurs types de contraintes de synchronisation qui sont:
• Si un lecteur demande à lire et qu'il y a une écriture en cours, la demande est mise en attente. De
même que si un rédacteur demande à écrire et qu'il y a au moins une lecture en cours, la demande
est mise en attente.
Dr. A. ABBAS 1
Examen système d’exploitation Département d’informatique, Université de Bouira
• Si un rédacteur demande à écrire et qu'il y a une écriture en cours, la demande est mise en attente.
Question :
- Écrire l'algorithme des processus lectures et rédacteur en utilisant les sémaphores.
Exercice 4 (5 pts) :
En se basant sur les sémaphores, écrire un programme utilisant 3 threads afin d'afficher la séquence
suivante: A, B, C, A, B, C...,
Où, le thread T1 affiche: A, le thread T2 affiche: B, et le thread T3 affiche: C,
}
}
Dr. A. ABBAS 2
Département d’informatique, Université de Bouira
Module : Système d'exploitation M1-ISIL (2021)
Examen de remplacement
Exercice 1 (4 pts) :
1. Pour exécuter en parallèle plusieurs instructions d'une même application, vous avez le choix
d’utiliser les appels système pthread_create() et fork(). Laquelle des deux possibilités à choisir ?
Pourquoi ?
- On choisi pthread _create ( ) car le fork( ) consomme beaucoup d’espace (duplication de
processus). Mais il faut faire attention au conflit d’accès aux objets partagés. (2 pts)
Exercice 2 (6 pts) :
Soit le schéma suivant décrivant les transitions d’un processus. Précisez dans le tableau ci-
dessous à quoi correspondent les transitions numérotées par 1, 2, 3, 4 et précisez quels sont
les événements qui provoquent chacune de ces transitions.
Nouveau Fin
1
Prêt En exécution
2
4 3
Bloqué
Exercice 3 (5 pts) :
En se basant sur les sémaphore, écrire un programme utilisant 3 threads (A, B et C) afin
d'afficher la séquence suivante: 1,2,3,1,2,3, 1,2,3, ....., où le thread A affiche le chiffre 1, le
thread B affiche le chiffre 2 et le thread C affiche le chiffre 3.
solution:
Dr. A. ABBAS 1
Département d’informatique, Université de Bouira
Module : Système d'exploitation M1-ISIL (2021)
#include <stdio.h>
#include <stdlib.h> void *C (void * arg){
#include <pthread.h> while (1) {
#include <semaphore.h> sem_wait(&my_sem3);
sem_t my_sem1,my_sem2,my_sem3; printf ("3,");
void *A (void * arg){ sem_post(&my_sem1);
while (1) {
sem_wait(&my_sem1); }
printf ("1,"); }
sem_post(&my_sem2); void main (int ac, char **av){
} pthread_t th1, th2,th3;
} sem_init (&my_sem1, 0, 1);
void *B (void * arg){ sem_init (&my_sem2, 0, 0);
sem_init (&my_sem3, 0, 0);
while (1) { pthread_create (&th1, NULL, &A, NULL) ;
sem_wait(&my_sem2); pthread_create (&th2, NULL, &B, NULL) ;
printf ("2,"); pthread_create (&th3, NULL, &C, NULL) ;
sem_post(&my_sem3); pthread_join (th1, NULL);
pthread_join (th2, NULL);
} pthread_join (th3, NULL);
} }
Exercice 4 (5 pts) :
Considérons un objet (une base de données par exemple) qui n'est accessible que par deux
catégories d'opérations : les lectures et les écritures. Plusieurs lectures (consultations)
peuvent avoir lieu simultanément ; par contre les écritures (mises à jour) doivent se faire en
exclusion mutuelle. Ce problème induit plusieurs types de contraintes de synchronisation
qui sont:
• Si un lecteur demande à lire et qu'il y a une écriture en cours, la demande est mise
en attente. De même que si un rédacteur demande à écrire et qu'il y a au moins une
lecture en cours, la demande est mise en attente.
• Si un rédacteur demande à écrire et qu'il y a une écriture en cours, la demande est
mise en attente.
Question :
- Écrire l'algorithme des processus lectures et rédacteur en utilisant les sémaphores.
Dr. A. ABBAS 2
Département d’informatique, Université de Bouira
Module : Système d'exploitation M1-ISIL (2021)
Test de remplacement
Exercice 1: 6 pts
Expliquer pour quoi le partage des ressources sans précaution particulière peut conduire à des
résultats imprévisibles.
Solution
La mise à jour concurrente peut générer des incohérences, où les ressources partagée, auront
des valeurs finales déférentes après l'exécution du même code. La cause de ces incohérences
est due à l'utilisation simultanée de la ressource partagée par plusieurs processus ou threads.
Pour expliquer ce fait, on donne l'exemple suivant:
20000
Exercice 2: 14 pts
En se basant sur le programme de l'exercice 3 de l'examen, écrire un autre programme
utilisant 3 threads (A, B et C) afin d'afficher la séquence suivante: 1,1,1, 2,3, 1,1,1, 2,3,
1,1,1, 2,3, ....., où le thread A affiche le chiffre 1, le thread B affiche le chiffre 2 et le thread C
affiche le chiffre 3.
#include <stdio.h> }
#include <stdlib.h>
#include <pthread.h> void *B (void * arg){
#include <semaphore.h>
while (1) {
sem_t my_sem1,my_sem2,my_sem3; sem_wait(&my_sem2);
sem_wait(&my_sem2);
void *A (void * arg){ sem_wait(&my_sem2);
printf ("2,");
while (1) { sem_post(&my_sem3);
sem_wait(&my_sem1);
printf ("1,"); }
sem_post(&my_sem2); }
}
Dr. A. ABBAS 3
Département d’informatique, Université de Bouira
Module : Système d'exploitation M1-ISIL (2021)
}
}
Dr. A. ABBAS 4
Examen système d’exploitation Département d’informatique, Université de Bouira
Exercice 1 (4 pts) :
Exercice 2 (6 pts) :
Soit le schéma suivant décrivant les transitions d’un processus. Précisez dans le tableau ci-dessous à quoi
correspondent les transitions numérotées par 1, 2, 3, 4 et précisez quels sont les événements qui
provoquent chacune de ces transitions.
Nouveau Fin
1
Prêt En exécution
2
4 3
Bloqué
Exercice 3 (5 pts):
Considérons un objet (une base de données par exemple) qui n'est accessible que par deux catégories
d'opérations : les lectures et les écritures. Plusieurs lectures (consultations) peuvent avoir lieu
simultanément ; par contre les écritures (mises à jour) doivent se faire en exclusion mutuelle. Ce
problème induit plusieurs types de contraintes de synchronisation qui sont:
• Si un lecteur demande à lire et qu'il y a une écriture en cours, la demande est mise en attente. De
même que si un rédacteur demande à écrire et qu'il y a au moins une lecture en cours, la demande
est mise en attente.
Dr. A. ABBAS 1
Examen système d’exploitation Département d’informatique, Université de Bouira
• Si un rédacteur demande à écrire et qu'il y a une écriture en cours, la demande est mise en attente.
Question :
- Écrire l'algorithme des processus lectures et rédacteur en utilisant les sémaphores.
Exercice 4 (5 pts) :
En se basant sur les sémaphores, écrire un programme utilisant 3 threads afin d'afficher la séquence
suivante: A, B, C, A, B, C...,
Où, le thread T1 affiche: A, le thread T2 affiche: B, et le thread T3 affiche: C,
}
}
Dr. A. ABBAS 2
Université de Bouira
Département d’informatique 3ième Année SI (2020/2021)
Module : système d'exploitation Durée : 1h
Examen Système d'exploitation
Exercice 1 (5 pts) :
1. Quelle est la différence entre un processus lourd et un processus léger (thread) ? (4pts)
Le processus lourd est créé par duplication (copie exacte du processus original) d'un processus existant.
Le deux processus lourd ne partage pas le même espace mémoire.
Le thread créateur et le thread créé partagent tous deux le même espace mémoire
2. Dans quel(s) état(s) peut se retrouver un processus après l'état Prêt? (1 pt)
Après l'état Prêt, un processus peut se trouver dans l'état exécution
Exercice 2 (8 pts) : Soit le programme suivant de synchronisation de deux threads avec l'utilisation de
sémaphores.
#include <stdio.h> void *thread2 (void * arg){
#include <stdlib.h> while(1) {
#include <pthread.h> sem_wait(&my_sem2); //(0.5 pt)
#include <semaphore.h> printf ("Je suis thread2,");
sem_t *my_sem1, *my_sem2; //(1 pt) sem_post(&my_sem1); //(0.5 pt)
}}
void *thread1 (void * arg) { void main (int ac, char **av){
while(1) { pthread_t *th1, *th2;
sem_wait(&my_sem1); // (0.5 pt) sem_init(&my_sem1, 0 ,1); //(0.5 pt)
printf ("Je suis thread1,"); sem_init(&my_sem2, 0 ,0); //(0.5 pt)
sem_post(&my_sem2); //(0.5 pt) pthread_create(&th1, NULL,&thread1, NULL) ;
} } pthread_create(&th2, NULL,&thread2, NULL) ;
pthread_join(th1, NULL);
pthread_join(th2, NULL);
printf ("Je suis main,");
}
Question :
1. Complétez ce programme pour qu'il affiche la séquence suivante : Je suis thread1, Je suis thread2,
Je suis thread1, Je suis thread2,....
2. Utiliser le programme précédent pour écrire un autre programme qui initialise une variable entière
cpt à 1 et qui crée deux threads p1 et p2. Le thread p1 incrémente cpt 10000 fois et le thread p2
décrémente cpt 10000 fois. Utiliser un sémaphore pour résoudre le problème de l’accès concurrent à
la variable cpt.
#include <stdio.h>
#include <stdlib.h> void* p2(void* arg){
#include <unistd.h> int i=0;
#include <pthread.h> while (i<10000){
#include <semaphore.h> sem_wait(&semaphore); (0.5 pt)
sem_t semaphore; (1 pt) cpt -=1;
int cpt =1; sem_post(&semaphore); (0.5 pt)
i++;
void* p1(void* arg){ }
int i=0; }
while (i<10000){ int main(void) {
sem_wait(&semaphore); (0.5 pt) pthread_t tache1, tache2;
cpt +=1; sem_init(&semaphore, 0, 1); (1 pt)
sem_post(&semaphore); (0.5 pt) pthread_create (&tache1, NULL, &p1, NULL);
i++; pthread_create (&tache2, NULL, &p2, NULL);
} pthread_join(tache1, NULL);
} pthread_join(tache2, NULL);
printf("cpt =%d:\n", cpt );
return 0;
Université de Bouira
Département d’informatique 3ième Année SI (2020/2021)
Module : système d'exploitation Durée : 1h
Examen Système d'exploitation
}
Exercice 3 (7 pts) :
On considère le problème du producteur consommateur. Le processus producteur, délivre des
messages à un processus consommateur. Le producteur produit le message dans la ZoneP, puis le
dépose dans le buffer. Le consommateur prélève un message du Buffer et le place dans la ZoneC où il
peut le consommer. Ce problème introduit plusieurs types de contraintes de synchronisation:
1. Un producteur ne doit pas déposer dans le buffer quand il n y a plus de place pour déposer ce qu’il a
produit.
2. Un consommateur ne doit pas prélever de messages quand le buffer est vide.
3. Producteurs et consommateurs ne doivent pas accéder en même temps au buffer.
Question :
Écrire l'algorithme des processus producteurs et consommateurs en utilisant les sémaphores.
Semaphore Mutex = 1, Plein = 0, Vide=n ; (2 pt)
Message tampon[];
Producteur ( ){ Consommateur( ) {
Message m ; Message m ;
Tantque Vrai faire Tantque Vrai faire
P(Vide); (1 pt) P(Plein); (1 pt)
m = creermessage() ; P(Mutex) ; (0.5 pt)
P(Mutex) ; (0.5 pt) m = LectureTampon();
EcritureTampon(m); V(Mutex) ; (0.5 pt)
V(Mutex) ; (0.5 pt) V(Vide); (1 pt)
V(Plein); (1 pt) Fin Tantque
FinTantque } }
Test
Exo1: Soit le graphe de précédence des processus {A, B, C, D, et E} (12 pts)
C D
A
B
E
- Réaliser la synchronisation de ces processus en utilisant les sémaphores.
Sémaphore S1=0, S2=0;S3=0
Exo1: Expliquez pas-à-pas comment s'exécute le programme suivant et donner le résultat d'affichage. (8 pts)
1. main () {
2. int y ;
3. y=0 ;
4. pid_t thr ;
5. thr =fork() ;
6. if (thr ==0) {
7. y=5 ;
8. prinf(‘‘y=%d\n’’, y) ;
9. } else
10. prinf(‘‘y=%d\n’’, y) ;
11. }
inst2et3: déclaration d'une varaible y de type int et affectation de 0
inst4: déclaration d'une varaible thr de type pid_t
inst5: création du processus fils suite à l'appel de la fonction fork() et affectation de la
valeur de retour à la variable thr
inst6: test la valeur de thr, si elle égale à 0 alors on est dans le fils
inst7: le processus fils affecte 5 à y
inst8: le processus fils affiche: y=5
inst9: si la valeur de thr différente de 0 alors on est dans le père
inst10: le processus père affiche: y=0
A. ABBAS 3 Bon
courage
Université de Bouira
Département d’informatique 3ième Année SI (2019/2020)
Module : système d'exploitation Durée : 1h
Examen de Rattrapage
Exercice 1 (4 pts) :
1. Qu’est-ce qu’un PCB et de quoi est-ce composé ? (1 pt)
PCB est une structure de données particulière appelée bloc de contrôle de processus (PCB : Process
Control Bloc) et dont le rôle est de reconstituer le contexte du processus.
PCB contient l'ensemble des informations dynamiques qui représente l‘état d‘ exécution d'un processus. Il
contient aussi des informations sur l'ordonnancement du processus (priorité du processus, les pointeurs
sur les files d'attente)
2. Dans quel(s) état(s) peut se retrouver un processus après l'état exécution? (1 pt)
Après l'état exécution, un processus peut se trouver dans l'une des états suivantes: Prêt, Bloqué ou Fin
3. Quelle est la différence entre un processus lourd et un processus léger (thread) ?
Le processus lourd est créé par duplication (copie exacte du processus original) d'un processus existant.
Le deux processus lourd ne partage pas le même espace mémoire. (1 pt)
Le thread créateur et le thread créé partagent tous deux le même espace mémoire (1 pt)
Exercice 2 (8 pts) :
On considère le problème du producteur consommateur. Le processus producteur, délivre des
messages à un processus consommateur. Le producteur produit le message dans la ZoneP, puis le
dépose dans le buffer. Le consommateur prélève un message du Buffer et le place dans la ZoneC où il
peut le consommer. Ce problème introduit plusieurs types de contraintes de synchronisation:
1. Un producteur ne doit pas déposer dans le buffer quand il n y a plus de place pour déposer ce qu’il a
produit.
2. Un consommateur ne doit pas prélever de messages quand le buffer est vide.
3. Producteurs et consommateurs ne doivent pas accéder en même temps au buffer.
Question :
Écrire l'algorithme des processus producteurs et consommateurs en utilisant les sémaphores.
Semaphore Mutex = 1, Plein = 0, Vide=n ; (2 pt)
Message tampon[];
Producteur ( ){ Consommateur( ) {
Message m ; Message m ;
Tantque Vrai faire Tantque Vrai faire
P(Vide); (1 pt) P(Plein); (1 pt)
m = creermessage() ; P(Mutex) ; (0.5 pt)
P(Mutex) ; (0.5 pt) m = LectureTampon();
EcritureTampon(m); V(Mutex) ; (0.5 pt)
V(Mutex) ; (0.5 pt) V(Vide); (1 pt)
V(Plein); (1 pt) Fin Tantque
FinTantque } }
Exercice 3 (8 pts) : Soit le programme suivant de synchronisation de deux threads avec l'utilisation de
sémaphores.
#include <stdio.h> void *thread2 (void * arg){
#include <stdlib.h> while (1) {
#include <pthread.h> sem_wait(&my_sem2) (0.5 pt)
#include <semaphore.h> printf ("Je suis thread2,");
sem_t * my_sem1, * my_sem2; (1 pt) sem_post(&my_sem1) (0.5 pt)
void *thread1 (void * arg) { }}
while (1) { void main (int ac, char **av){
sem_wait(&my_sem1) (0.5 pt) pthread_t th1, th2;
printf ("Je suis thread1,"); sem_init (&my_sem1, 0 ,0); (0.5 pt)
sem_post(&my_sem2) (0.5 pt) sem_init (&my_sem2, 0 ,1); (0.5 pt)
} } pthread_create (&th1, NULL,&thread1, NULL) ;
pthread_create (&th2, NULL,&thread2, NULL) ;
pthread_join (&th1, NULL);
pthread_join (&th2, NULL);
Question :
1. Complétez ce programme pour qu'il affiche la séquence suivante : Je suis thread1, Je suis thread2,
Je suis thread1, Je suis thread2,....
2. Utiliser le programme précédent pour écrire un autre programme qui initialise une variable entière
cpt à 1 et qui crée deux threads p1 et p2. Le thread p1 incrémente cpt 10000 fois et le thread p2
décrémente cpt 10000 fois. Utiliser un sémaphore pour résoudre le problème de l’accès concurrent à
la variable cpt.
#include <stdio.h> void* p2(void* arg){
#include <stdlib.h> int i=0;
#include <unistd.h> while (i<10000){
#include <pthread.h> sem_wait(&semaphore); (0.5 pt)
#include <semaphore.h> cpt -=1;
sem_t semaphore; (0.5 pt) sem_post(&semaphore); (0.5 pt)
int cpt =1; (0.5 pt) i++;
void* p1(void* arg){ }
int i=0; }
while (i<10000){ int main(void) {
sem_wait(&semaphore); (0.5 pt) pthread_t tache1, tache2;
cpt +=1; sem_init(&semaphore, 0, 1); (0.5 pt)
sem_post(&semaphore); (0.5 pt) pthread_create (&tache1, NULL, &fonc1, NULL);
i++; pthread_create (&tache2, NULL, &fonc2, NULL);
} pthread_join(tache1, NULL);
} pthread_join(tache2, NULL);
printf("cpt =%d:\n", cpt ); (0.5 pt)
return 0;
}
Question :
1. Complétez ce programme pour qu'il affiche la séquence suivante : Je suis thread1, Je suis thread2,
Je suis thread1, Je suis thread2,....
2. Utiliser le programme précédent pour écrire un autre programme qui initialise une variable entière
cpt à 1 et qui crée deux threads p1 et p2. Le thread p1 incrémente cpt 10000 fois et le thread p2
décrémente cpt 10000 fois. Utiliser un sémaphore pour résoudre le problème de l’accès concurrent à
la variable cpt.
#include <stdio.h> void* p2(void* arg){
#include <stdlib.h> int i=0;
#include <unistd.h> while (i<10000){
#include <pthread.h> sem_wait(&semaphore); (0.5 pt)
#include <semaphore.h> cpt -=1;
sem_t semaphore; (0.5 pt) sem_post(&semaphore); (0.5 pt)
int cpt =1; (0.5 pt) i++;
void* p1(void* arg){ }
int i=0; }
while (i<10000){ int main(void) {
sem_wait(&semaphore); (0.5 pt) pthread_t tache1, tache2;
cpt +=1; sem_init(&semaphore, 0, 1); (0.5 pt)
sem_post(&semaphore); (0.5 pt) pthread_create (&tache1, NULL, &fonc1, NULL);
i++; pthread_create (&tache2, NULL, &fonc2, NULL);
} pthread_join(tache1, NULL);
} pthread_join(tache2, NULL);
printf("cpt =%d:\n", cpt ); (0.5 pt)
return 0;
}
Exo1: 3 pts
Quelle est la différence entre section critique et ressource critique ?
a. Une section critique (SC): est un ensemble d'instruction d'un programme qui peuvent engendrer
des résultats imprévisibles (ou incohérents) lorsqu'elles sont exécutées simultanément par des
processus différents. Une SC est une suite d'instructions qui opèrent sur une ou plusieurs ressources
partagées (critiques) et qui nécessitent une utilisation exclusive de ces ressources.
b. On appelle ressource critique tout objet informatique qui peut faire l'objet d'un accès concurrent
(ou simultané) par plusieurs processus.
Exo2: 7 pts
Soit le graphe de processus suivant:
A
B E
C
Exo3: 5 pts
Donner le rôle de chaque élément ci-dessous.
fork() ; est un moyen offre par SE afin de créer des processus, par duplication d'un processus existant.
wait() ; Permet au père d'attendre le premier enfant qui se termine
pthread_join() ; Attendre la fin d'exécution d’un thread
sem_wait() ; équivalente à l'opération P (S) et retourne toujours 0
Local_irq_disable(); masquées les interruptions.
Test 2 - version 2
Exo1: 3 pts
La valeur initiale d’un sémaphore est égale à K, que représente cette valeur ?
K représente le nombre d'unités d'une ressource R utilisables par un ou plusieurs processus à un instant
t. On peut aussi définir k comme le nombre d'autorisations d'accès à une section critique à un instant t.
Exo2: 7 pts
Soit le graphe de processus suivant:
A
B E
C
Exo3: 5 pts
Donner le rôle de chaque élément ci-dessous.
waitpid(); Attendre l’enfant d’identificateur pid se termine
kill() ; Le processus père mis fin à l'exécution de l'un de ces fils
while (wait(NULL)>=0) ; Attendre la fin de chaque enfant
pthread_self() ; Retourne le TID du thread
sem_post()): est équivalente a l'opération V(S)
Test 2 - version 3
Exo1: 6 pts
Quelles sont les opérations d'un sémaphore qui s’exécutent d’une manière indivisible ?
Et que ce qu'une section critique.
Les opération d'un sémaphore qui s'exécute d'une manière indivisible sont P(S) et V(S)
On appelle ressource critique tout objet informatique qui peut faire l'objet d'un accès
concurrent (ou simultané) par plusieurs processus.
Exo2: 9 pts
Écrire un programme qui crée 2 processus fils, l'un des fils affiche les entiers de 1 à
10, l'autre fils affiche les entiers de 11 à 20. Le père devra attendre la fin de ses deux
fils et afficher quel a été le premier processus qui a terminé.
1. #include <sys/types.h>
2. #include <unistd.h>
3. #include <stdio.h>
4. int main(int argc, char **argv) {
5. pid_t p1,p2,premier;
6. int i;
7.
8. p1 = fork();
9. if (p1 == 0){
10. for (i=1; i<11; i++)
11. printf("%d \n", i);
12. exit() ;
13. }
14.
15. p2 = fork();
16. if (p2 == 0){
17. for (i=11; i<21; i++)
18. printf("%d \n", i);
19. exit() ;
20. }
21.
22. premier =wait(NULL);
23. wait(NULL);
24.
25. printf(" le premier processus qui a terminé est %d \n", premier);
26. return 0;
}
-----------------------------------------------------------------------------------------------------------------
Test 2 - version 4
Exo1: 5 pts
La valeur initiale d’un sémaphore est égale à K, que représente cette valeur ?
K représente le nombre d'unités d'une ressource R utilisables par un ou plusieurs processus à
un instant t. On peut aussi définir k comme le nombre d'autorisations d'accès à une section
critique à un instant t.
Exo2: 10 pts
Écrire un programme qui crée 3 processus fils, chaque fils affiche son PID et se
termine. Le père devra attendre la fin de ses 3 fils et afficher quel a été le dernier
processus qui a terminé.
Exo1: 3 pts
Quelle est la différence entre section critique et ressource critique ?
a. Une section critique (SC): est un ensemble d'instruction d'un programme qui peuvent
engendrer des résultats imprévisibles (ou incohérents) lorsqu'elles sont exécutées simultanément par
des processus différents. Une SC est une suite d'instructions qui opèrent sur une ou plusieurs
ressources partagées (critiques) et qui nécessitent une utilisation exclusive de ces ressources.
b. On appelle ressource critique tout objet informatique qui peut faire l'objet d'un accès
concurrent (ou simultané) par plusieurs processus.
Exo2: 7 pts
Soit le graphe de processus suivant:
A
B E
C
D
Réaliser la synchronisation des ces processus en utilisant les sémaphores
Sémaphore SA=0, SD=0
Exo3: 5 pts
Expliquez pas-à-pas comment s'exécute le programme suivant. (3pts)
1. main () {
2. int x ;
3. x=0 ;
4. pid_t pro;
5. pro=fork();
6. if (pro==0)
7. x=1
8. prinf(‘‘x=%d\n’’,x) ;
9. else
10. prinf(‘‘x=%d\n’’,x) ;
}
Exo1: 3 pts
La valeur initiale d’un sémaphore est égale à K, que représente cette valeur ?
K représente le nombre d'unités d'une ressource R utilisables par un ou plusieurs processus à un instant
t. On peut aussi définir k comme le nombre d'autorisations d'accès à une section critique à un instant t.
Exo2: 7 pts
Soit le graphe de processus suivant:
A
B E
C
Exo3: 5 pts
Expliquez pas-à-pas comment s'exécute le programme suivant. (3pts)
11. main () {
12. int x ;
13. x=0 ;
14. if (fork() !=0)
15. x=1 // processus père affecte 1 à x
16. else
17. x=2 // processus fils affecte 2 à x
18. prinf(‘‘x=%d\n’’,x) ;
}
inst4: appel de la fonction fork() pour créer un processus fils et test la valeur de retour de la
fork s'elle est différente de zéro;
inst5: Si la valeur de retour de fork () différente de zéro alors on est dans le père qui affecte 1
àx
inst7: Si la valeur de retour de fork () égale à zéro alors on est dans le fils qui affecte 2 à x
inst8: le processus père affiche: x=1 et le processus fils affiche x=2
Solution Test groupe 1
Exo1: 3 pts
Quelle est la différence entre section critique et ressource critique ?
a. Une section critique (SC): est un ensemble d'instruction d'un programme qui peuvent
engendrer des résultats imprévisibles (ou incohérents) lorsqu'elles sont exécutées simultanément par
des processus différents. Une SC est une suite d'instructions qui opèrent sur une ou plusieurs
ressources partagées (critiques) et qui nécessitent une utilisation exclusive de ces ressources.
b. On appelle ressource critique tout objet informatique qui peut faire l'objet d'un accès
concurrent (ou simultané) par plusieurs processus.
Exo2: 7 pts
Soit le graphe de processus suivant:
A
B E
C
D
Réaliser la synchronisation des ces processus en utilisant les sémaphores
Sémaphore SA=0, SD=0
Exo3: 5 pts
Expliquez pas-à-pas comment s'exécute le programme suivant. (3pts)
1. main () {
2. int x ;
3. x=0 ;
4. pid_t pro;
5. pro=fork();
6. if (pro==0)
7. x=1
8. prinf(‘‘x=%d\n’’,x) ;
9. else
10. prinf(‘‘x=%d\n’’,x) ;
}
Exo1: 3 pts
La valeur initiale d’un sémaphore est égale à K, que représente cette valeur ?
K représente le nombre d'unités d'une ressource R utilisables par un ou plusieurs processus à un instant
t. On peut aussi définir k comme le nombre d'autorisations d'accès à une section critique à un instant t.
Exo2: 7 pts
Soit le graphe de processus suivant:
A
B E
C
Exo3: 5 pts
Expliquez pas-à-pas comment s'exécute le programme suivant. (3pts)
11. main () {
12. int x ;
13. x=0 ;
14. if (fork() !=0)
15. x=1 // processus père affecte 1 à x
16. else
17. x=2 // processus fils affecte 2 à x
18. prinf(‘‘x=%d\n’’,x) ;
}
inst4: appel de la fonction fork() pour créer un processus fils et test la valeur de retour de la
fork s'elle est différente de zéro;
inst5: Si la valeur de retour de fork () différente de zéro alors on est dans le père qui affecte 1
àx
inst7: Si la valeur de retour de fork () égale à zéro alors on est dans le fils qui affecte 2 à x
inst8: le processus père affiche: x=1 et le processus fils affiche x=2
Université de Bouira - Département d’Informatique Année 2020-2021
Module : Systèmes d'Exploitation 3ème année Licence SI
Série TD N° 1
Exercice 1 :
Écrire un algorithme puis réaliser un découpage en tâches t1,...,tn de l'expression suivante:
Exercice 2 :
Combien de processus le programme suivant crée-t-il ?
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
int main() {
fork();
fork();
fork();
return EXIT_SUCCESS;
}
Exercice 3 :
. Dessiner l’arbre généalogique des processus engendrés par le programme ?
# include <unistd.h>
# include <stdio.h>
int main() {
pid_t pid; int i;
for (i=0; i<3;i++) {
pid = fork();
if (pid < 0 ){
printf ("le fork ( ) a échoué \n") ;
}
else if (pid == 0){
printf(" je suis le processus : %d, mon père est : %d\n", getpid(), getppid()) ;
}
else{
printf("je suis le processus : %d, mon père est : %d\n", getpid(), getppid()) ;
}
} return 0 ;
}
Exercice 4 :
Écrire un programme en C qui lance 5 fils et attend la fin de leur exécution pour se terminer.
Nom:
Test de TD
Prénom:
Grroupe :
Exercice 1: Quelle est la différence entre une ressource critique et une section critique ?
a. Une section critique (SC): est un ensemble d'instruction d'un programme qui peuvent
engendrer des résultats imprévisibles (ou incohérents) lorsqu'elles sont exécutées
simultanément par des processus différents. Une SC est une suite d'instructions qui opèrent
sur une ou plusieurs ressources partagées (critiques) et qui nécessitent une utilisation
exclusive de ces ressources.
b. On appelle ressource critique tout objet informatique qui peut faire l'objet d'un accès
concurrent (ou simultané) par plusieurs processus.
Exercice 2: Soit l'expression suivante :
B E
C
3+6+6
Exercice 1: Les moniteurs sont considérés comme des outils de synchronisation "avancés"
par rapport aux sémaphores. Expliquez brièvement pourquoi. ?
les moniteurs cachent les détails de synchronisation (pas P(s) V(S) dans le code des
processus). Le code des processus devient moins lourd.
Permet de regrouper dans un module spécial appelé moniteur toutes les sections
critiques d'un même problème. Avoir un seul processus active dans le moniteur à tout
instant
• Utilisez les sémaphores pour forcer l’exécution des actions du processus A avant celles de
B et C. Les actions de B et C s’exécutent en concurrence (en parallèle).
Exercice 2: On considère trois processus P1, P2 et P3 concurrents. Les codes des processus
P1, P2 et P3 sont les suivants:
Intégrer des sémaphores afin d'afficher la séquence suivante:
1,1,1, 2,3, 1,1,1, 2,3, 1,1,1, 2,3, .....
S1=3,S2=0,S3=0
P1 ( ) { P2 ( ) { P3 ( ) {
while(TRUE) { while(TRUE) { while(TRUE) {
p(s1); p(s2); p(s2); p(s2); p(s3);
printf("1,"); printf("2,"); printf("3,");
V(S2); V(S3); V(S1);V(S1);V(S1) ;
}} }} }}
Test 2 de TD SE L3- INFO
Nom:
Prénom:
Groupe :
Groupe 1
3+6+6
Exercice 2: Considérez les pprocessus P1, P2, P3 et P4, et les sémaphhores S1 et S2. Les
processus sont lancés en concuurrence.
Nom:
Prénom: Groupe 3
Groupe :
3+6+6
Exercice 1: Les moniteurs sont considérés comme des outils de synchronisation. Expliquez
brièvement le rôle des primitives wait() et signal() ??
wait(x) : suspend ou bloque l'exécution du processus (thread) appelant wait et le met en
attente de x et autorise un autre processus en attente du moniteur a y entrer dans ce moniteur.
signal(x) : débloqué un processus en attente de la condition x.
Exercice 2:Soient deux variables x et y communes à deux processus déclarées comme suit :
int x = 0 ; int y = 0 ;
Les deux processus exécutent les codes suivants :
Processus P1{ Processus P2{
x = x + 1; x = x * 2;
y = y + 1; y = y * 2;
printf("x=%d,y=%d\n", x, y); } printf("x=%d, y=%d\n", x, y);}
1. Ces processus s'exécutent sur un système dont la politique d'ordonnancement est du type
temps partagé. Quelles peuvent être les couples de valeurs affichées par chacun des deux
processus ? 6
Les couples de valeurs affichées
2. Utilisez les sémaphores pour synchroniser les deux processus au niveau des sections
critiques, puis donnez les couples de valeurs affichées par chacun des deux processus. 6
Prénom :
Section : Test TD M1
3k +2562k
2. Quelle est le nombre de blocs de donnée que ce système de fichiers peut supporter ?
266+2563