Système et Réseaux : TD4, sémaphores
Système et Réseaux : TD4, sémaphores
février 2024 — Pierre Rousselin
Remarque : par soucis de concision, les inclusions des fichiers d’en-tête et certains tests d’appels système
sont omis dans les programmes présentés dans ce sujet.
Exercice 1 : Exemples de sémaphores
Dans toutes les questions qui suivent, on suppose donnée la fonction main, les globales suivantes, et
les déclarations suivantes :
void *hop(void *); sem_init(&sem2, 0, Y);
void *plop(void *); pthread_create(&th_hop, NULL, hop, NULL);
void travailler(void); pthread_create(&th_plop, NULL, plop, NULL);
sem_t sem1; pthread_join(th_hop, NULL);
sem_t sem2; pthread_join(th_plop, NULL);
int res; sem_destroy(&sem1);
int main(void) sem_destroy(&sem2);
{ return 0;
pthread_t th_hop, th_plop; }
sem_init(&sem1, 0, X);
Les valeurs initiales X et Y des sémaphores seront données pour chaque question. La fonction travailler
représente un travail, arbitraire, qui ne modifie ni les sémaphores, ni la variable res. Donner le com-
portement du programme ou, si une situation de compétition ou une étreinte mortelle (deadlock, le
programme est bloqué) sont possibles.
1. X = 0, Y = 1 et les fonctions hop et plop sont 2. Mêmes fonctions avec X = 1 et Y = 1.
les suivantes : 3. Mêmes fonctions avec X = 0 et Y = 0.
void *hop(void *arg) {
travailler(); 4. Mêmes fonctions avec X = 0 et Y = 2.
sem_wait(&sem2); 5. Les fonctions hop et plop sont les suivantes, X
res = 42;
= 1 et sem2 n’est pas utilisé. La fonction main
sem_post(&sem1);
affiche le contenu de res après avoir join les
travailler();
sem_wait(&sem2); deux threads. Attention, l’incrémentation n’est
res = 93; pas supposée atomique.
sem_post(&sem1); void *hop(void *arg) {
return NULL; for (int i = 0; i < 3; i++) {
} sem_wait(&sem1);
void *plop(void *arg) { res++;
travailler(); sem_post(&sem1);
sem_wait(&sem1); }
printf("%d\n", res); return NULL;
sem_post(&sem2); }
travailler(); void *plop(void *arg) {
sem_wait(&sem1); return hop(NULL);
printf("%d\n", res); }
sem_post(&sem2);
6. Même chose pour X = 2.
return NULL;
} 7. Même chose pour X = 0.
––- * ––-
Exercice 2 : A, puis B
On considère le programme suivant :
L2 Informatique et double-licence — 2024 – 2025 1 Université Sorbonne Paris Nord
Système et Réseaux : TD4, sémaphores
void boulot(int n); }
int main(void) {
boulot(100000); void boulot(int n) {
printf("A\n"); for (int i = 0; i < n; i++)
boulot(100000); ;
printf("B\n"); }
1. Faire faire le boulot à des threads :
— un nouveau thread fait le boulot puis quand il a fini écrit A sur le terminal ;
— un autre nouveau thread fait le boulot puis quand il a fini écrit B sur le terminal.
2. Quel est le risque si le thread initial n’attend pas les autres ?
3. L’ordre des affichage est-il fixé à l’avance ?
4. À l’aide d’un sémaphore, faire en sorte que A soit toujours affiché avant B. Attention, ces threads
doivent pouvoir travailler en même temps !
5. Reprendre l’exercice avec trois boulots et l’écriture de A, puis B, puis C, dans cet ordre.
––- * ––-
Exercice 3 : interblocage (deadlock)
On considère le programme (idiot) suivant :
void *f1(void *arg); sem_t *sem = arg;
void *f2(void *arg); sem_wait(sem);
int main(void) printf("f1: sem[0] mis à 0\n");
{ sem_wait(sem + 1);
pthread_t th1, th2; printf("f1: sem[1] mis à 0.\n");
sem_t sem[2]; sem_post(sem + 1);
sem_init(sem, 0, 1); sem_post(sem);
sem_init(sem + 1, 0, 1); return NULL;
pthread_create(&th1, NULL, f1, sem); }
pthread_create(&th2, NULL, f2, sem); void *f2(void *arg)
{
pthread_join(th1, NULL); sem_t *sem = arg;
pthread_join(th2, NULL); sem_wait(sem + 1);
sem_destroy(sem); printf("f2: sem[1] mis à 0\n");
sem_destroy(sem + 1); sem_wait(sem);
printf("f2: sem[0] mis à 0\n");
return 0; sem_post(sem);
} sem_post(sem + 1);
void *f1(void *arg) return NULL;
{ }
Donner les différents scénarios possibles dans l’exécution de ce programme (on suppose que les affi-
chages sont atomiques, ce qui est faux mais simplifie l’exercice).
––- * ––-
L2 Informatique et double-licence — 2024 – 2025 2 Université Sorbonne Paris Nord