Licence et IUP2 informatique 2003/2004
Écrivez aussi un petit programme appelé pinfo qui teste cette fonction.
Puis écrivez un programme qui crée un processus fils, lequel exécute le programme pinfo de votre voisin. Appelez votre fonction getpinfo() d'une part dans le processus père, et d'autre part dans le processus fils avant l'appel à exec..().
Il s'agit ici de compter les lignes, mots et caractères de plusieurs fichiers. Le programme doit :
- lancer un processus fils pour chacun des noms de fichiers passés en paramètre,
- chaque fils doit exécuter le programme wc sur le fichier dont il s'occupe,
- le père doit finalement afficher le nombre de fils qui ont échoué (par exemple parce que le fichier n'existe pas ou n'est pas lisible).
Important : évitez de lancer ce programme sur un grand nombre de fichiers !
Dans un deuxième temps, vous modifierez ce programme de façon à ce qu'il ne lance jamais plus de 10 processus simultanés. Vous pouvez tester ce nouveau programme, par exemple par : ``wcp /usr/include/*'' (il y a plus de 200 fichiers et répertoires dans /usr/include).
Enfin, posez vous la question de savoir ce qu'il manque à votre programme pour que le père puisse, à la fin de l'exécution de tous ses fils, afficher les totaux (comme le fait le programme wc).
Cet exercice est optionnel.
Écrivez un programme qui parcourt une hiérarchie de répertoires. L'unique paramètre du programme est un nom de répertoire. Chaque processus doit parcourir un répertoire et :
- lancer un processus fils pour chaque sous-répertoire,
- attendre la fin de ses fils,
- afficher le nombre de fichiers et le nombre de sous-répertoires du répertoire dont il a la charge.
Il s'agit donc d'un parcours postfixé d'une hiérarchie.
Notes :
Utilisez opendir(3), readdir(3) et closedir(3) pour parcourir le contenu d'un répertoire ;
Utilisez stat(2) pour déterminer si une entrée du répertoire est un fichier ou un répertoire (vous pouvez ignorer les autres cas).
Si vous craignez de générer trop de processus, vous pouvez utiliser la commande ``ulimit -u 10'' pour limiter (ici à 10) le nombre de processus fils du shell courant.
Question : est-il possible d'inverser l'ordre d'affichage (c'est-à-dire d'afficher les renseignements sur un répertoire avant les renseignements sur ses sous-répertoires) ?
Écrire le programme correspondant à la commande : ``ps -fade | grep $LOGNAME | sort'', selon les deux schémas d'organisation père-fils des processus suivants :
Voici un exemple pour :
Cet exercice est optionnel.
Un tube nommé est un fichier spécial qui se comporte comme un pipe, mais qui est présent sur le filesystem. Un processus peut ouvrir un tube nommé soit en lecture soit en écriture, puis y lire ou y écrire. Un tube nommé est créé soit par la commande mkfifo(1) ou mknod(1), soit par un programme utilisant l'appel système mknod(2). L'ouverture, la lecture, l'écriture et la fermeture d'un tube nommé se font exactement comme pour un fichier normal.
Note : Si vous travaillez sur une machine Linux, votre répertoire est monté par NFS depuis une machine serveur. Il se trouve que NFS ne supporte pas bien les tubes nommés. Pour éviter les problèmes, il suffit de le créer sur un disque local, par exemple dans le répertoire /tmp.
Réalisez deux programmes, un écrivain lisant l'entrée standard et écrivant dans un tube nommé, et un lecteur lisant le contenu du tube nommé et écrivant sur sa sortie standard. Remarque : il existe une commande système qui permet de faire cela très facilement, inutile de la programmer en C.
Créez un tube nommé, et lancez un écrivain et un lecteur, chacun dans sa fenêtre. Vérifiez que vos programmes produisent le résultat attendu.
Lancez ensuite plusieurs écrivains et un seul lecteur, tous sur le même tube nommé. Observez ensuite ce qui se passe si vous avez plusieurs lecteurs sur le même tube nommé. Essayez de brancher un écrivain sur le tube nommé de votre voisin (qui doit, lui, lancer un lecteur).
Essayer d'imaginez comment vous pourriez mettre au point un système de communication multipoint (c'est-à-dire plusieurs utilisateurs pouvant chacun lire ce que tous écrivent, et écrire à tous) à l'aide de tubes nommés.
On reprend ici l'exemple du word-count sur plusieurs fichiers, traité chacun par un processus différent. Il y a ici deux différences par rapport à l'exercice 2 : il faut écrire une fonction qui compte le nombre de caractères (et de lignes et de mots si vous voulez) présents dans un fichier ;
Le processus lance autant de threads qu'il reçoit de fichiers en paramètres (mais pas plus de 10 en même temps), et écrit le nombre de caractères du fichier dont il a la charge dans une variable globale. Mettez en uvre un dispositif permettant au thread maître d'imprimer le total du nombre de caractères (et de lignes et de mots...) à la fin de son exécution.
Note : N'oubliez pas l'option de compilation -D_REENTRANT, et l'option de linkage -lpthread si nécessaire.
Remarque. Ce système n'est pas correct en tant que tel : que se passe-t-il si plusieurs processus accèdent à l'entier en lecture puis en écriture en même temps ?
Peut-on éviter ce problème ?
Reprenons l'exemple du word-count sur plusieurs fichiers, traité chacun par un thread différent. Il faut ici utiliser des processus, qui communiquent par l'intermédiaire d'un segment de mémoire partagée et de signaux.
Évitez de stopper et relancer les processus effectuant le travail, cette opération est trop coûteuse : une fois que les 10 processus sont créés, distribuez leur le travail à effectuer par l'intermédiaire du segment de mémoire partagée et des signaux (par exemple).
Mettez en uvre un dispositif permettant au programme père d'imprimer le total du nombre de caractères (et de lignes et de mots...) à la fin de son exécution.
Écrivez un programme qui utilise un fichier projeté en mémoire pour effectuer une inversion par ligne, c'est-à-dire qu'il imprime les lignes du fichier dans l'ordre inverse de leur apparition (la commande tac(1) fait ça).
Pour confectionner un quatre-quart, il faut : du sucre, du beurre, de la farine, des oeufs. Six cuisinières (6 threads) et un épicier (le thread master) collaborent de la manière suivante :
Implémentez ce mécanisme, en évitant les boucles actives, les interblocages et les risques de conflit d'accès aux données partagées. Vous pouvez utiliser tous les mécanismes de synchronisation entre threads que vous connaissez.
Utilisez la fonction time(2) pour afficher la durée de confection de chaque gateau dans le thread master. Affichez également le status du thread master à chaque seconde à l'aide de la fonction setitimer(2) et des redirections de signaux.
(en cours)
This document was generated using the LaTeX2HTML translator Version 2002-2-1 (1.70)
Copyright © 1993, 1994, 1995, 1996,
Nikos Drakos,
Computer Based Learning Unit, University of Leeds.
Copyright © 1997, 1998, 1999,
Ross Moore,
Mathematics Department, Macquarie University, Sydney.
The command line arguments were:
latex2html -split 0 -local_icons -show_section_numbers tp
The translation was initiated by Vincent Loechner on 2004-11-04
Vincent Loechner 2004-11-04