|
|
Institut National des Télécommunications
Télécom INT 2è année
TP Noté CSC4508/M2 du 07/06/06
Modalités
Durée : 3 heures
Les trois questions sont indépendantes les unes des autres.
Le barême est donné à titre indicatif des poids
entre les différentes questions. Seront
notés :
- La clarté du code,
- Le fait que le code compile (sans warning),
- Le fait que le code répond correctement à la
question posée,
- Le fait que le retour de chaque appel système, s'il
y en
a un, est testé et géré (traitement
d'erreur),
- Le fait que les ressources système
réservées pendant l'exécution du programme
sont libérées à la fin de
l'exécution.
La «livraison» de votre travail en fin de TP
noté se fera par remise de votre copie à l'enseignant et
par
envoi d'un mail à Michel.Simatic@int-evry.fr
(sujet «CSC4508/M2:TP noté») avec en pièce
jointe le fichier d'extension tgz constitué de
la manière suivante :
cd votreRepertoireDeTravailPourCS22M1 tar cvfz $USER.tgz TPNote2006
Préparation
cd votreRepertoireDeTravailPourCS22M1 cp ~simatic/CS22M1/tPNote2006.tgz . tar xvfz tPNote2006.tgz cd TPNote2006
Question 1 : Questions de cours (5 points)
Pour chacune des questions ci-dessous, répondez sur votre copie
ou
bien dans le fichier Q1/reponse1.txt (dans ce dernier
cas, indiquez sur votre copie "Réponse dans Q1/reponse1.txt "
).
Question 1.1 : À propos des threads
On considère le code suivant :
#include <stdio.h> #include <stdlib.h>
#include <pthread.h>
#define NBAFFICHAGE 5
void ajoute(char *val) { static char cur;
if (val != NULL) cur = *val; else cur = cur + 1;
printf("cur = %c\n", cur); }
void *pthread_func(void *arg) { int i; char *val = (char *)arg; ajoute(val);
sleep(2);
for (i = 0; i < NBAFFICHAGE; i++) ajoute(NULL);
pthread_exit(NULL); }
int main(int argc, char **argv) { pthread_t thread1, thread2;
char val1 = 'a'; char val2 = 'A';
if (pthread_create(&thread1, NULL, pthread_func, &val1)) { perror("pthread_create"); exit(EXIT_FAILURE); }
if (pthread_create(&thread2, NULL, pthread_func, &val2)) { perror("pthread_create"); exit(EXIT_FAILURE); }
pthread_join(thread1, NULL); pthread_join(thread2, NULL);
return EXIT_SUCCESS; }
À un moment donné, combien y-a-t-il au maximum
dans la
mémoire du processus d'occurrences de:
Question 1.2 : Ordonnancement
Un(e) de vos collègues vient de lancer le programme
suivant :
/*******************************/ /* Essai de sched_setscheduler */ /*******************************/
#include <stdlib.h> #include <unistd.h> #include <stdio.h> #include <sched.h> #include <sys/types.h> #include <sys/wait.h>
#define FATAL(msg) {\ char m[128]; \ sprintf(m, "%s in %s:%d:%s", msg, __FILE__, __LINE__, __func__); \ perror(m); \ abort(); \ }
/**********************************************************************/ /* Code execute par le processus enfant */ /**********************************************************************/ void codeEnfant() { struct sched_param sp;
sp.sched_priority = sched_get_priority_max(SCHED_FIFO); if (sched_setscheduler(0,SCHED_FIFO,&sp) < 0) { FATAL("sched_setscheduler"); }
while(1){ } }
/**********************************************************************/ /* Programme principal */ /**********************************************************************/ int main(int argc, char* argv[]) { int status;
switch (fork()) { case -1: FATAL("fork"); break; case 0: codeEnfant(); break; default: wait(&status); }
return EXIT_SUCCESS; }
Que conseillez-vous pour arrêter son programme ? Justifiez votre
réponse.
Qu'auriez-vous répondu si votre collègue avait
utilisé SCHED_RR
à la place de SCHED_FIFO
?
Question 1.3 : Mémoire
Le système d'exploitation MS-DOS a été
conçu en 1981 de sorte qu'un programme s'exécutant sur ce
système ne pouvait accéder qu'à 640 Ko de
mémoire vive. Or, à partir de 1988, les ordinateurs sous
MS-DOS disposant d'au moins 1 Mo de mémoire vive devenaient
communs.
Pour tirer parti de cette mémoire vive supplémentaire,
des compilateurs ont alors proposé le mécanisme
appelé "mécanisme de recouvrement" (overlay) :
- Le programmeur pouvait spécifier que des sections de
son code devaient être rangées dans des fichiers
appelés "fichiers de recouvrement" (ou fichiers d'overlay).
- Ainsi un programme exécutable était
constitué par :
- Un fichier exécutable contenant le main du programme.
- Un ou plusieurs fichiers de recouvrement, chargés
dans la mémoire au delà des 640 Ko au moment de
l'exécution.
- La zone de 640 Ko contenait une zone appelée "zone
de recouvrement". Pour être utilisé, un fichier de
recouvrement devait être transféré dans cette zone
de recouvrement. Le programmeur souhaitant appeler une fonction
située dans un fichier de recouvrement devait au
préalable invoquer une primitive permettant le transfert du
fichier de recouvrement dans la zone de recouvrement. L'appel de la
fonction pouvait ensuite se faire normalement.
NB : si le programmeur avait ensuite besoin d'invoquer une
fonction
présente dans un autre fichier de recouvrement, il devait
préalablement demander le transfert de cet autre fichier qui
recouvrait (remplaçait) alors le premier fichier dans la zone de
recouvrement.
- Voici un exemple de main
d'un programme qui utilisait 3 fonctions a et b stockées dans le
fichier fichierRecouvrementAB
et 2 fonctions y et z stockées dans le
fichier fichierRecouvrementYZ
:
int main(){ chargerFichierRecouvrement(fichierRecouvrementAB); a(); /* NB : a() appelle b(), ce qui ne pose aucun problème */ /* puisque b() est présente dans la zone de recouvrement */ chargerFichierRecouvrement(fichierRecouvrementYZ); /* NB : ce fichier recouvre le fichier */ /* fichierRecouvrementAB : a() et b() */ /* ne sont donc plus accessibles */ y(); z(); chargerFichierRecouvrement(fichierRecouvrementAB); a(); return EXIT_SUCCESS; }
Présentez au moins un avantage et au moins deux
inconvénients du mécanisme de recouvrement par rapport
à un mécanisme de mémoire virtuelle.
Question 2 : Il était une fois... (7
points)
Il était une fois une jeune et jolie jeune fille qui s'appelait
Blanche-Neige. Tous les matins, les chauds rayons du soleil venait la
tirer de son doux et beau sommeil. Pleine d'énergie, elle
réveillait les
sept nains (avec qui elle vivait) afin qu'ils ne soient pas en retard
pour leur travail à la mine.
Une fois habillés, puis arrivés devant la mine, les sept
nains devaient éventuellement attendre que les trois ours (qui
travaillaient parfois à la mine pendant que les nains n'y
étaient pas)
en soient sortis (les ours et les nains n'arrivaient pas à
cohabiter dans la mine : les ours estimaient que la barbe des nains
grattait ; quant
aux nains, ils trouvaient que les ours ne savaient pas siffler en
travaillant). Une fois les ours sortis (pour rejoindre la tendre Bouton
d'Or, mais cela est une autre histoire), les nains entraient dans la
mine pour commencer leur travail qu'ils entrecoupaient de pauses
régulières au cours desquelles ils se
réconfortaient à l'aide d'un verre d'alcool du pays
préparé par la Grand-mère du Petit Chaperon rouge.
Ils trouvaient ces verres sur un plateau (situé à
l'entrée de la mine), les buvaient (cul sec !) et les jetaient
par dessus leur épaule (ces nains étaient d'origine
russe). Ce plateau (qui pouvait contenir au plus quatre verres pleins)
était rempli par 8 adorables petites mésanges qui
faisaient constamment l'aller-retour Maison de Mère-Grand/Mine
avec un verre rempli (ces mésanges attendant qu'une place soit
libérée
sur le plateau si jamais le plateau contenait quatre verres pleins).
Le soir venu, les nains quittaient la mine (permettant ainsi aux ours
de rentrer dans la mine s'ils avaient décidé de venir y
travailler) et rentraient à la
maison. Là, sans se préoccuper que le soleil soit
couché ou non, Blanche-Neige leur faisait "Bisou Bonne Nuit"
pour qu'ils s'endorment. Elle allait ensuite se coucher en
attendant une nouvelle journée pleine d'aussi merveilleuses
aventures...
Cette histoire, vous l'avez raconté des centaines de fois
à l'enfant dont vous êtes le ou la baby-sitter et... vous
craquez ! Aussi, vous avez décidé de
réfléchir à un algorithme qui servirait de base
à un programme racontant automatiquement cette histoire.
Vous envisagez les tâches suivantes :
- Une tâche Soleil racontant l'histoire du point de vue
du soleil. Elle exécute l'algorithme suivant :
faire
Ecrire "Je me lève"
dormir(12 heures)
Ecrire "Je
me couche"
dormir(12
heures)
tant que VRAI
- Une tâche BlancheNeige racontant l'histoire du point
de vue de Blanche-Neige. Elle exécute l'algorithme suivant :
faire
Ecrire "Le soleil me reveille"
Ecrire "Je
réveille les nains"
Ecrire "Je
vis ma vie sans les nains"
Ecrire "Je
fais Bisou Bonne Nuit
à chaque nain"
Ecrire "Je dors"
tant que VRAI
- 7 tâches Nain (une pour chacun des nains) racontant
l'histoire du point de vue de chaque nain. Elles exécutent
l'algorithme suivant :
faire
Ecrire "Blanche-Neige me reveille"
Ecrire "Je
vais à la mine"
Ecrire
"J'attends de pouvoir entrer dans
la mine"
Ecrire
"J'entre dans la mine"
faire
Ecrire "Je travaille"
dormir(nombreDeMinutesAleatoire)
Ecrire "Je prends ma
pause"
Ecrire "Je prends un
verre plein"
Ecrire "Je bois cul
sec !"
tant que
continuerTravail()
Ecrire "Je
quitte la mine"
Ecrire "Je
rentre à la maison"
Ecrire
"Blanche-Neige me fait Bisou
Bonne Nuit"
Ecrire "Je
m'endors"
tant
que VRAI
- 3 tâches Ours (une pour pour chacun des ours)
racontant l'histoire du point de vue de chaque ours. Elles
exécutent l'algorithme suivant :
faire
Ecrire "Je vis
une autre histoire avec
Bouton d'Or"
dormir(nombreDeMinutesAleatoire)
si
oursDecideDAllerTravaillerALaMine() == VRAI alors
Ecrire "Je
vais à la mine"
Ecrire "J'attends de pouvoir
entrer dans la mine"
Ecrire "J'entre dans la mine et je
travaille"
dormir(nombreDeMinutesAleatoire)
Ecrire "Je quitte la mine"
finsi
tant
que VRAI
- 8 tâches Mesange (une pour chacune des
mésanges) racontant l'histoire du point de vue de chaque
mésange. Elles exécutent l'algorithme suivant :
faire
Ecrire "Je prends un verre plein chez Mère-Grand, je vais
à la mine et j'attends de pouvoir le déposer sur le
plateau"
Ecrire "Je dépose le verre sur le
plateau"
tant
que VRAI
NB : pour les
questions 2.1 et 2.2, vous pouvez
répondre sur votre copie ou bien dans le fichier Q2/reponse2.txt .
Dans ce dernier
cas, indiquez sur votre copie "Réponses dans Q2/reponse2.txt ".
Question 2.1 : Identification des paradigmes (2
points)
Indiquez les différents types de problème de
synchronisation auxquels vous allez être confrontés pour
implémenter
ce programme (exclusion mutuelle, cohorte,
producteur/consommateur...) en précisant, pour chaque
problème,
ses acteurs (par exemple, si vous trouvez qu'il y a un paradigme de
lecteurs/rédacteur dans lequel intervient le "soleil", vous
devez préciser si le "soleil" est lecteur ou rédacteur).
Pour chacune des questions ci-dessous, répondez sur votre copie
ou
bien dans le fichier Q2/reponse.txt (dans ce dernier
cas, indiquez sur votre copie "Réponse dans Q2/reponse.txt "
).
Question 2.2 : Conception à l'aide de
sémaphores (5
points)
À l'aide de sémaphores IPC (munis de leurs
opérations P() et V() ) et de
variables que vous
déclarerez de manière globale (i.e. ils seront
accessibles à partir de n'importe quelle
procédure/fonction de votre programme) et initialiserez,
complétez les algorithmes envisagés pour que le programme
raconte correctement l'histoire.
Question 3 : Nains, mésanges et code (8 points)
Vous décidez d'implémenter une version simplifiée
des algorithmes de la question 2. Les tâches suivantes sont
envisagées :
- 7 tâches Nain (une pour chacun des nains) racontant
l'histoire (simplifiée) du
point de vue de chaque nain. Elles exécutent l'algorithme
suivant :
faire
Ecrire
"Nain <numéroNain> : Je
travaille"
dormir(1 seconde)
Ecrire "Nain <numéroNain> : Je
prends ma
pause"
Ecrire "Nain <numéroNain> : Je
prends un
verre plein sur le plateau"
Ecrire "Nain <numéroNain> : Je
bois cul
sec !"
tant
que VRAI
- 8 tâches Mesange (une pour chacune des
mésanges)
racontant l'histoire (simplifiée) du point de vue de chaque
mésange. Elles exécutent
l'algorithme suivant :
faire
Ecrire "Mésange <numéroMésange> : Je prends
un verre plein chez Mère-Grand, je vais
à la mine et j'attends de pouvoir le déposer sur le
plateau"
Ecrire "Mésange
<numéroMésange> : Je dépose le verre sur le
plateau"
tant
que VRAI
Question 3.1 : Conception (2 points)
Décrire dans Q3/reponse31.txt les algorithmes
envisagés dans le cas de l'utilisation de threads, avec des mutex et des
conditions (le plateau sera représenté par un tableau
d'entier de 4 cases : une case à 0 signifie que cette partie du
plateau est vide tandis qu'une case à 1 signifie que cette
partie du plateau contient un verre plein.
NB : Si vous ne voyez pas comment écrire ces algorithmes
(et que vous souhaitez, malgré tout, répondre à la
question 3.2), vous
avez la possibilité de faire "appel à un cabinet de
consulting" en
demandant
une indication à l'enseignant qui notera qu'il vous a
aidé : donc, le(s) point(s) de barême
associé(s)
à cet(/ces) algorithmes ne vous
sera(/seront) pas comptabilisé(s).
Question 3.2 : Implémentation avec des threads (6
points)
Implémenter (avec des threads,
des conditions et des mutex) la conception envisagée à la
question
3.1 en modifiant le fichier Q3/conteDeFeeOuCauchemar.c
NB : <numéroNain> sera remplacé par un
numéro entre 1 et 7 tandis que
<numéroMésange> sera remplacé par un
numéro entre 1 et 8
|