Vous êtes sur la page 1sur 4

APP-2GE Anné e 2018-2019

Nom : Prénom : Signature :

Examen – 1h
Principes des systèmes d'exploitation – Unix/Linux
Document UNIX & Le Shell autorisé – Feuille A4 sur le cours

Question 1 (6). Concepts de base


1.1) Commenter les 4 transitions du diagramme d’état suivant dans un ordonnancement à priorités
fixes?

1- le processus en cours est mis en attente car un processus de priorité supérieure est prêt (et sera
activé en 4)

2- le processus en cours fait une entrée-sortie et est mis en pause, ce qui permet à un processus de
même priorité ou de priorité inférieur de s’exécuter.

3- la fin de l’entrée sortie déplace le processus suspendu dans l’état prêt.

4- le processus le plus prioritaire dans l’état prêt est activé.

1.2) A quel problème fait référence une section critique et comment le résout-on ?

Une section critique est une partie de code dans laquelle des instructions manipulent des données
partagées entre deux processus ou deux threads.

La concurrence d’accès à des données partagées peut induire des incohérences dans les calculs et
impose donc d’assurer l’exclusion mutuelle d’accès à ces données partagées.

La solution consiste à utiliser un sémaphore d’exclusion mutuelle (1 seul jeton) appelé habituellement
un mutex. Le mutex ne peut être acquis que par un seul processus/thread.

1/4
Question 2 (6). Pratique des Shell scripts

2.1) Réaliser un script SERVEUR cyclique qui effectue les opérations suivantes :
• compte de manière périodique toutes les secondes le nombre de processus et stocke ce nombre
dans une variable NBP.
• affiche la valeur de la variable NBP lors de la réception d’un signal USR1 (Réaliser un handler
d’interruption).
2.2) Réaliser un script CLIENT qui demande de façon périodique l’affichage de compteur NBP au
serveur (toutes les n secondes, n est le second paramètre du script)

Rappel :
ps u liste les processus courants de l’utilisateur
wc -l compte les lignes d’entrée
sleep 1 met en attente le processus pendant une seconde
trap ‘action’ USR1 associe une action qu signal USR1
kill -USR1 X envoie le signal USR1 au processus de numéro X

# le SERVEUR =========================================

trap ‘echo Valeur de NBP : $NBP’ USR1 # activation de l’action sur réception du signal USR1

while 1
do
sleep 1 # attente 1 sec
NBP=`ps -u | wc -l` # comptage des processus
done

# le CLIENT ============================================
# deux paramètres : le PID du père, la période

while 1
do
sleep $2 # attente d’un nombre de seconde donné par le paramètre 2
kill -USR1 $1 # envoi du signal USR1 au processus de PID donné par le paramètre 1
done

2/4
Question 3 (8) Programmation multi-tâche en C
3.1) Nous allons analyser le comportement du programme donné en 4 questions.
a. Commentaire des lignes 4 et 5.
b. Commentaire des lignes 6 à 8.
c. Commentaire des lignes 11 à 13.
d. Qui exécute la ligne 15. Expliquer.

1 int main (void) {


2 pid_t pid, pid_ret;
3 int i, status;
4 pid = fork () ;
5 if (pid == 0) {
6 printf ("Processus: %d - %d\n", getpid()) ;
7 execl ("/opt/X11/bin/xterm", "xterm", "-e", "echo Bonjour; sleep 10", NULL);
8 printf ("Fin Processus.\n");
9 }
10 else {
11 printf ("Processus %d\n", getpid()) ;
12 pid_ret=waitpid(pid, &status, 0);
13 printf ("Fin processus.\n");
14 }
15 printf ("Bye, bye! %d\n", getpid());
16 }

a-Commentaire des lignes 4 et 5.

Création d’un processus fils par la fonction fork. La valeur de retour de fork est stockée dans la
variable pid. Si le pid est égal a 0 on est dans le processus fils, si le pid est différent de 0, alors on est
dans le processus père et ce numéro correspond au pid du fils.

b-Commentaire des lignes 6 à 8.


Ce code correspond au code exécuté par le processus fils. La fonction exec lance une fen^tre
terminal ou s’affiche un message. La fonction exec remplace le code du fils par le code de xterm. La
ligne 8 n’est donc pas exécutée.

c-Commentaire des lignes 11 à 13.

Il s’agit ici du code exécuté par le père, qui attend la terminaison du fils (ligne 12) par waitpid et
affiche un message de fin (ligne 13) ;

d-Qui exécute la ligne 15. Expliquer.

La ligne 15 n’est exécutée que par le père, puisque le fils a remplacé son code par la fonction exec
(voir réponse b)

3/4
3.2) Quel problème présente ce processus à threads multiples ? Comment le résoudre ?

1 #include <pthread.h>
2
3 float result;
4
5 void *fct_log(void *arg) {
6 int x, *px=arg; x=*px;
7 while (1) {
8 result=2*x; usleep(150000);
9 result=log10(result) ; usleep(150000);
10 printf("result =%.2f\n", result);
11 }
12 return NULL;
13 }
14
15 /* Programme principal */
16 int main(int argc, char *argv[]) {
17 pthread_t tid1, tid2;
18
19 int x1=5; int x2=50;
20
21 pthread_create(&tid1, NULL, (void *)fct_log, (void *)&x1);
22 usleep (300000);
23 pthread_create(&tid2, NULL, (void *)fct_log, (void *)&x2);
24
25 pthread_join(tid1, NULL);
26 pthread_join(tid2, NULL);
27
28 return(0);
29 }

Le problème est lié au partage de la donnée result entre deux threads qui exécutent la même fonction
fct_log.

Cette fonction calcule log(2x), x étant le paramètre, différent pour les deux thtreads.

Ce calcul se fait en deux instructions ligne 8 (2x), et ligne 9 (log).

Les deux threads peuvent s’interrompre entre ces deux instructions ce qui peut générer un résultat
incorrect.

Il faut que les lignes 8 et 9 soient protégées par un mutex.

Il faut :
-déclarer et initialiser un mutex au début du programme
pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;

-prendre le mutex avant la ligne 8


pthread_mutex_lock(&mut);

- relâcher le mutex après la ligne 9


pthread_mutex_unlock(&mut);

4/4

Vous aimerez peut-être aussi