CNAM-Lorraine - ACCOV/NFP103 TD
Transcription
CNAM-Lorraine - ACCOV/NFP103 TD
CNAM-Lorraine - ACCOV/NFP103 TD-TP numéro 1 Programmation multiprocessus S. Vialle 9 mars 2007 Ce TD-TP étudie la programmation multiprocessus au travers de plusieurs applications. L’énoncé s’articule en 6 parties de difficulté progressive : 1. Etude des méthodes de création de threads et d’allocation de sémaphores en C sous Linux ou Windows, ou en Java 1.5. 2. Conception d’un programme multithread de type producteur-consommateur traditionnel, destiné à réaliser un prétraitement (lecture et filtrage de fichiers) et un traitement (calcul sur les données lues) en parallèle. 3. Conception d’une variante d’un système producteur-consommateur, où le consommateur n’est pas bloqué en cas d’absence de messages à lire, et en profite pour poursuivre un traitement de fond. 4. Etude des méthodes de création de processus et d’allocation de sémaphores et de mémoire partagée en C sous Linux ou Windows. 5. Conception d’une application multiprocessus de gestion d’impressions, comprenant des processus clients soumettant des impressions, et des processus serveurs d’impression réalisant ces impressions. 6. Conception d’une application multiprocessus de gestion de mots de passes, selon un schéma lecteurs-rédacteur. Pour chaque exercice on rendra les listings des programmes, des exemples d’exécution, et des explications de la démarche employée. Les points 1 et 4 seront étudiés lors de l’implantation des codes (en TP). Les points 2, 3, 5 et 6 seront d’abord étudiés en TD, puis repris en TP pour y être implantés. 1 1 Création de threads et allocation de sémaphores L’objectif de cet exercice est de vous familiariser avec la création de threads, l’allocation de sémaphores et leur utilisation, l’attente de la mort des threads fils, et la libération des sémaphores, dans l’environnement choisi (C+Linux, C+Windows ou Java 1.5). 1. Implantez un programme qui crée deux threads fils. Chaque thread fils affichera un message (”coucou”), et le thread principal (le programme principal) attendra la mort des ses threads fils pour se terminer lui même. Le thread principal affichera un message avant et après ce point de synchronisation, afin que l’on puisse vérifier le bon fonctionnement de ce premier programme multithread. 2. Déclarez une variable globale dans le programme principal (variable globale au processus), allouer et initialiser un sémaphore binaire afin de programmer une exclusion mutuelle. Créez deux threads fils qui vont tous deux lire puis écrire dans la variable globale en réalisant une exclusion mutuelle sur cette variable. Après la mort des threads fils, libérez le sémaphore. Affichez les résultats de tous les appels systèmes (ou attrapez toutes les exceptions) pour vérifier SYSTEMATIQUEMENT que tous les appels système ont bien réussi. 2 2 Filtrage de fichier et traitement de données On désire lire un fichier de données (ASCII), en supprimer les commentaires (filtrage) et réaliser un traitement sur les données extraites. La lecture complète du fichier comportera de nombreuses opérations d’E/S, bloquantes et longues (accès à un périphérique). Si on parallélise la lecture du fichier et le traitement des données déjà lues, le processeur fait des calculs pendant les temps d’attente des E/S. La figure 1 illustre ce mécanisme. Fichiers sur disques Mémoire partagée P C Lecture des fichiers Traitement des données Fig. 1 – Système parallèle (multithread) de filtrage de fichiers et de traitement de données Pour cela, une solution possible est un système de deux threads accomplissant un protocole producteur - consommateur. Un thread producteur lit un fichier de données, le filtre, et stocke les données dans une mémoire partagée, produisant ainsi des messages à destination du thread consommateur. Le consommateur récupère les données dans la mémoire partagée (du processus) et exécute un traitement sur chacune d’elles. Cette technique permet normalement de gagner du temps en réalisant les E/S en parallèle de certains calculs. Mais cela peut dépendre des proportions relatives des temps de lecture et de traitement de l’application, et des capacités matérielles de l’ordinateur. Travail demandé : On implantera le système multithreads de filtrage de fichiers et de traitement de données suivant : – Le thread producteur lit le fichier data.txt. Le producteur stocke les entiers lus dans la mémoire partagée, et ignore les lignes de commentaires. – Le thread consommateur récupère les entiers déposés dans la mémoire partagée et applique sur chacun d’eux la fonction calcul(i) (à définir rapidement, ex. : calcule récursivement la factorielle de i). – Sur la fin du fichier, le thread producteur stocke le message -1 et se termine. Le thread consommateur se termine à son tour quand il 3 détecte le message -1. Le fichier de données comprendra des lignes contenant chacune un seul entier positif, et des lignes de commentaires commençant par un 0 suivit d’un blanc et d’un texte quelconque. La fin du fichier sera marqué par une ligne contenant uniquement l’entier -1. 4 3 Traitement de données pilotable Considérons un mécanisme d’acquisition et de traitement de données en continu, mais réagissant à des commandes de l’utilisateur. En général une saisie de commande au clavier est bloquante pour le programme qui l’exécute, ce qui empêche de poursuivre en même temps un traitement de fond. Avec un système à deux threads, seul celui qui saisit les commandes se bloque en attendant une entrée au clavier. L’autre thread peut alors poursuivre ses activités, et traiter les commandes seulement lorsqu’elles arrivent (sous forme de messages produits et stockés par le processus de saisie de commande). La figure 2 schématise la structure d’un tel système. Buffer partagee de messages Traitement de donnees C P Processus de fond (consommateur) Interface homme−machine (producteur) Fig. 2 – Système (multithreads) piloté d’acquisition et de traitement de données Les commandes traitées peuvent être par exemple : – halt qui termine le processus de traitement des données, – stop qui stoppe le traitement des données s’il était actif, – cont qui provoque la reprise du traitement s’il était stoppé, – show qui demande au processus de traitement de fournir un bilan de ses activités. Travail demandé : On implantera un système de traitement de données pilotable autour du protocole producteur - consommateur non bloqué. La tache de fond du consommateur sera d’appeler la procédure calcul(i) (définie précédemment). Le consommateur signalera à l’écran le nom des commandes qu’il traitera. Dans le cas de la commande show il affichera également la valeur du paramètre passé à la procédure calcul lors de son dernier appel. 5 4 Création de processus et allocation de sémaphores et de mémoire partagée Après une programmation de systèmes multithreads, l’objectif de cet exercice est de vous familiariser avec la création de processus et l’allocation et libération de zones de mémoire partagée entre plusieurs processus au sein d’un même ordinateur. 1. Implantez deux applications (deux programmes distincts) qui allouent ou récupèrent une zone de mémoire partagée et allouent un même sémaphore binaire. L’une des deux applications sera appelée le ”serveur” et sera lancée en premier (elle fera l’initialisation du sémaphore et de la mémoire partagée). La deuxième sera appelée le ”client”. 2. Les deux processus liront et écriront dans la mémoire partagée en implantant une exclusion mutuelle sur la variable accédée concurremment. 3. Le client finira par entrer dans la mémoire partagée une valeur que le serveur reconnaı̂tra comme un code d’arrêt. Dès lors le client ne manipulera plus le sémaphore ni la mémoire partagée (il s’arrêtera), et le serveur libérera la mémoire partagée et le sémaphore, et s’arrêtera à son tour. Comme précédemment, vous afficherez systématiquement le résultat des appels systèmes, pour vérifier leur bonne exécution. 6 5 Simulateur de spooling On considère un système de gestion d’impressions disposant de plusieurs imprimantes. On désire pouvoir lancer des impressions en parallèle depuis plusieurs terminaux, et que chacune soit exécutée le plus rapidement possible sur n’importe quelle imprimante libre. On supposera les imprimantes toutes regroupées dans la même salle . . . Imprimantes Spooler (demon) Spooler (demon) Spooler (demon) Demons d’impressions Memoire partagee Utilisateurs demandant des impressions Fig. 3 – Exemple de système de gestion d’un parc d’imprimantes Il s’agit d’un système de P processus déposant des demandes d’impression (imprime), et de C processus démons gérant chacun une imprimante et réalisant des impressions (imprimed), voir figure 3. Le protocole correspondant est du type P producteurs et C consommateurs, accédant tous à une mémoire partagée où sont stockées les demandes d’impressions. Travail demandé : On écrira une commande de demande d’impression et un programme de démon d’impression, respectivement imprime et imprimed. La commande d’impression prendra comme seul paramètre un entier qui représentera l’identificateur du fichier. Cet entier sera récupéré depuis la ligne de commande. L’exécution de la commande imprime consistera à simuler une demande d’impression. Pour cela elle déposera un message constitué de l’identificateur du fichier, et exécutera une attente (sleep(20)) dans sa 7 section critique. De plus elle signalera à l’écran son entrée et sa sortie de section critique. Le démon d’impression prendra comme seul argument le nom de l’imprimante qu’il gérera (passé par la ligne de commande). Le travail d’un démon consistera à consommer des messages et à simuler des impressions. Pour cela il affichera l’identificateur du fichier qu’il imprime (le message), et exécutera une attente (sleep(30)) dans sa section critique. De plus il affichera son entrée et sa sortie de section critique. Par convention dans le TL, un démon d’impression se terminera après avoir effectué 3 impressions. On ouvrira une fenêtre de commande pour chaque imprimante que l’on voudra simuler, dans lesquels on lancera le démon correspondant, et quelques fenêtres de commande dans lesquelles on effectuera des demandes d’impressions. On vérifiera le bon fonctionnement de l’ensemble. 8 6 Gestionnaire de password Considérons un système informatique dans lequel un groupe d’utilisateurs accèdent à un service via un programme leur demandant au départ un mot de passe. Ce mot de passe sera le même pour tout le groupe. Ce pourrait être par exemple un service de documentation payant et forfaitaire auprès duquel une société aurait souscrit un abonnement d’un mois, renouvelable. Tous les employés de la société pourraient accéder à ce service en entrant le mot de passe, éventuellement en même temps, mais seulement pendant un mois. La figure 4 illustre ce système. Utilisateurs Disque et fichiers des mots de passe Maitre Fig. 4 – Système d’interrogation et de gestion d’un service de documentation Pour ce type de prestation c’est la société offrant le service de documentation qui impose le mot de passe et le change tous les mois. Le nouveau mot de passe n’est communiqué à la société cliente que si elle renouvelle son abonnement. Donc, le fichier conservant le mot de passe du client est accédé régulièrement en lecture à chaque consultation de la part du client, et de temps en temps en écriture par la société de documentation pour changer autoritairement le mot de passe. Toutefois un mot de passe ne peut être changé qu’à condition qu’il n’y ait pas d’utilisateurs en train de le consulter à cet instant. Il s’agit d’un protocole de type lecteurs - rédacteur, sur un fichier de mots de passe, avec priorité simple aux lecteurs. Travail demandé : On réalisera un programme client testant la validité d’un mot de passe saisi au clavier, et un programme maitre permettant de changer le mot de passe. Le programme client se terminera immédiatement en cas de saisie 9 incorrecte du mot de passe, et sur l’entrée de ’quit’ en cas de connexion réussie. On ouvrira une fenêtre de commande dans laquelle on exécutera un programme maitre pour définir un premier mot de passe. Puis, on ouvrira ensuite plusieurs fenêtres de comamnde dans lesquelles on établira des connexions au service de documentation en exécutant des programmes client. On changera ensuite le mot de passe en exécutant un nouveau programme maitre, et on vérifiera que les futures connections dépendent bien du nouveau mot de passe. Les programmes client et maitre maintiendront le fichier passwd ouvert durant toute la saisie du mot de passe au clavier. Ceci imposera une section critique importante permettant de vérifier aisément les deux règles suivantes : – Plusieurs programmes client peuvent accéder au fichier passwd en même temps. – Un programme maitre réalise un accès exclusif au fichier passwd, ne pouvant y accéder que s’il n’y a plus d’utilisateurs connectés, et empêchant toute connexion d’utilisateur pendant le changement de mot du passe. 10