TP noté 2018-2019
Modalités
Durée : 3 heures
Tous documents autorisés.
Les exercices 2, 3 et 4 sont indépendants les uns des autres. Aussi, n'hésitez pas à lire tout le sujet avant de commencer pour déterminer l'ordre dans lequel vous souhaitez traiter les questions.
Le barème est donné à titre indicatif des poids entre les différents exercices.
Préparation
Livraison
La « livraison » de votre travail en fin de TP noté se fera par remontée sous Moodle (rubrique « TP noté de 3 heures ») du fichier d'extension tgz constitué de la manière suivante :
Serveur d'impression (8 points)
2 points
Le programme exercice2/imprime.c simule une application d'impression qui attend de la part de l'utilisateur des noms de fichier à imprimer et les envoie à l'imprimante (l'impression étant simulée par un sleep de quelques secondes).
Telle qu'elle est écrite, l'utilisateur doit attendre qu'un fichier soit imprimé pour pouvoir donner le nom d'un autre fichier.
Modifier l'application exercice2/q1/imprime.c de sorte qu'à chaque fois que l'utilisateur a entré un nom de fichier, un thread est créé pour s'occuper de l'impression de ce fichier.
2 points
4 points
On ne crée plus un thread à chaque demande d'impressions. On crée au démarrage de l'application un ensemble de threads de taille MAXNBTHREADS = 3 threads. Chaque thread se met en attente d'une impression, imprime puis se met en attente d'une nouvelle impression. De plus, une zone tampon circulaire de taille MAXNBIMPRESSIONS = 5 est utilisée pour stocker la file d'impressions. L'accès à l'imprimante reste exclusif.
Copier le programme précédent dans le répertoire exercice2/q3/, puis le modifier pour utiliser un pool de threads.
Bulletins de notes (6 points)
Afin de corriger de multiples problèmes dans un système d'information poussif, il est décidé de réécrire complètement le système de gestion des notes des étudiants. Pour cela, 3 fichiers sont utilisés: etudiants.dat contient la liste des étudiants, cours.dat contient la liste des cours, et notes.dat contient la liste des notes.
Chacun de ces fichiers est constituté d'une suite de structures sous cette forme:
Afin de permettre un accès rapide à un étudiant à partir de son identifiant, l'emplacement d'un étudiant dans le fichier est déterminé par son identifiant. Ainsi, l'étudiant dont id vaut 0 est stocké au début du fichier, celui dont l'id vaut 1 est stocké à sizeof(struct etudiant) octets du début du fichier, etc.
Les cours sont stockés de la même façon : le cours d'id 0 est placé au début, le cours d'id 1 est placé à sizeof(struct cours) du début du fichier, etc.
Ce programme est chargé d'éditer les bulletins de notes. Le but est d'obtenir un affichage comme celui-ci:
- void print_bulletins() parcoure le fichier etudiants.dat, affiche le nom de chaque étudiant et appelle la fonction print_bulletin ;
- void print_bulletin(struct etudiant *e) parcoure le fichier notes.dat et, pour chaque note attribuée à l'étudiant e, appelle la fonction print_note ;
- void print_note(struct etudiant *e, struct note *n) recherche (dans cours.dat) le cours correspondant à la note n, et affiche le nom du cours et la note obtenue.
Complétez le programme exercice3/q1/notes.c pour implémenter ces fonctions.
On envisage maintenant de paralléliser l'édition de bulletins de notes en lançant plusieurs threads s'exécutant en parallèle. Chaque thread serait chargé d'éditer le bulletin d'un étudiant, et les fonctions print_note et print_bulletin seraient donc exécutées de manière concurrente.
Le code des fonctions print_note et print_bulletin que vous avez produit à la question précédente risque-t-il de poser problème dans ce cas ?
Répondez en justifiant votre réponse dans le fichier exercice3/reponses.txt
Recopiez le programme exercice3/q1/notes.c dans le répertoire exercice3/q3/notes.c, puis modifiez le pour mmaper le fichier cours.dat en mémoire au démarrage du programme. Modifiez également la fonction print_note pour qu'elle accède au fichier via la zone mmapée.
XV6 - Mémoire partagée (8 points)
Commencez par donner le code de xv6 que vous avez réalisé lors du TP9 (implémentation d'une mémoire partagée). Pour cela, exécutez les commandes suivantes en les adaptant :
Si vous n'avez pas fait le TP9 ou que le code produit n'est pas utilisable, vous pouvez vous baser sur le corrigé en exécutant les commandes suivantes à la place:
2 points
Dans xv6, ajoutez l'appel système int getppid() qui retourne le PID du processus parent. Pour cela, vous pouvez utiliser les deux champs pid et parent de la structure struct proc.
1 point
Dans xv6, ajoutez le programme utilisateur test_getppid.c qui affiche le PPID du processus.
2 points
Dans le fichier exercice4/reponses.txt, présentez l'implémentation de la fonction sys_shm_attach en vous appuyant sur le code que vous avez rendu à la question 4.a. Cette présentation doit expliquer l'algorithme principal implémenté ainsi que les mécanismes évitant les problèmes (détection d'erreur, verrouillage, etc.)
2 points
- si le message peut s'afficher dans certains cas, donnez les conditions dans lesquelles le message s'affiche
- si le message s'affiche toujours, expliquez le mécanisme qui le garanti
- si le message ne s'affiche jamais, expliquez le mécanisme qui le garanti
- Le message bonjour s'affiche toujours car lorsqu'un segment de mémoire partagée est crée, shm_create initialise les pages à 0 grace à un appel à memset. La page est donc remplie de 0, donc *addr != 42.
- Le message au revoir ne s'affiche jamais. L'instruction *addr = 42 écrit la valeur 42 au début de la première page du segment de mémoire partagée. Le segment est ensuite détaché, puis attaché à une autre addresse, et addr2 pointe alors sur le début de la première page du segment de mémoire partagée. Donc *addr2 == 42, et le message "au revoir" ne s'affiche pas.
1 point
Lorsqu'un processus est dupliqué (avec l'appel système fork), il serait souhaitable que les pages mémoires partagées par le processus père soient également accessible par le processus fils.
Expliquez dans le fichier exercice4/reponses.txt comment implémenter un tel mécanisme.