TP/TD 4 : Signaux, Mémoire partagée, Files de messages Cours Les

publicité
ASR2 - L3 Informatique - ENS Lyon
Année 2013-2014
A. Benoit, A.Isoard, A.Lefray et D. Zaidouni
TP/TD 4 : Signaux, Mémoire partagée, Files de messages
Cours
Learn !
Les Signaux
Les signaux permettent de signaler un évènement exceptionel mais peuvent également servir pour
établir une communication inter-processus. Différents évènements peuvent générer un signal :
— Une erreur programme (division par zero ou adresse invalide).
— Une requête utilisateur d’interruption ou de terminaison d’un programme (suspend : C-z, terminate C-c).
— La terminason d’un processus fils.
— L’expiration d’un timer ou d’une alarme.
— Un appel à kill ou raise par le même processus.
— Un appel à kill d’un autre processus.
— L’échec d’une tentative d’opération d’I/O.
Attention, en règle générale, les signaux ne peuvent être émis qu’entre processus de même utilisateur
(à l’exception de SIGCONT).
Lorsqu’un signal est généré, il est marqué comme pending puis devient soit delivered et est transmis au processus, ou est blocked auquel cas le signal reste en attente jusqu’à ce qu’il soit unblocked.
Lorsqu’il est délivré, le signal peut être :
— Géré par un comportement par défaut.
— Géré par un code spécifique (handler).
— Ignoré.
Pour bloquer des signaux, il suffit de positioner leur flag dans le masque des signaux du processus
via la fonction sigprocmask. À noter que SIGKILL et SIGSTOP ne peuvent être bloqués. Pour attendre
des signaux, il suffit de faire appel à sigsuspend. Pour définir un handler de signaux, il suffit de faire
appel à signal (gestion simple) ou sigaction (gestion avancée).
Les signaux : signal, alarm, pause, kill
Using smoke for signals is unsafe.
Pour afficher la liste des signaux, exécuter la commande kill -l.
1. Pourquoi bloquer un signal ?
Solution:
Eviter une interruption en section critique (signal handler). Tester si un signal n’est pas arrivé
(check des flags) et ainsi éviter qu’il puisse se produire juste après le test et avant tout code.
2. Quel le masque de signaux d’un processus fils après un fork ?
Solution:
Il hérite du masque du processus père.
1
3. Ecrire un programme timeout qui reçoit comme paramètre un temps t et le pid d’un processus,
et qui tue le processus au bout de t secondes.
Solution:
Voir fichier signaux.c.
4. Quel est le principal inconvénient de cette méthode de communication ?
Solution:
Il n’est pas possible d’associer du contenu à un message autre que le numero de signal. Elle est
plutôt réservée à la synchronisation ou à la détection de problèmes exceptionnels.
La mémoire partagée : mmap
Sharing memory ? We got photos for that !
L’appel noyau mmap(2) est l’appel qui se cache derrière malloc. Il permet d’allouer un plage mémoire d’addresse virtuelle avec les protections désirées. Il est par exemple possible d’allouer de la
mémoire partagée par deux processus après un fork grace au flag MAP_SHARED (voir page man).
1. Écrire un programme mettant en jeux deux processus qui communiquent par mémoire partagée.
(attention à la synchro)
Solution:
Voir fichier shared_mem.c.
2. Citez des avantage des transferts par mémoire partagée ? Un inconvénient ?
Solution:
Ils sont sans copie et sont donc très efficace, de plus il n’est pas nécessaire de linéariser les données
(une structure basée sur des pointeurs continuera de fonctionner).
Cependant il faut se synchroniser par un autre moyen pour éviter de modifier les données avant
qu’elles n’aient été traitées.
Les fifo : mkfifo, write, read
!!
La fonction mkfifo(3) permet de crée un fichier spécial de type First In First Out (FIFO). Ces
fichiers se comportent comme les pipe du TP précédent : l’écriture est virtuelle, tout comme la lecture,
et il n’est pas possible de se déplacer dans le fichier. Ainsi, les données disparaissent après lecture.
Suivant le comportement du système, l’écriture et/ou la lecture peuvent être bloquants. La seule
garantie fournie est que la lecture lit les données dans l’ordre dans lequelle elles sont écrites. La lecture
attends en général qu’il y ait assez de donnée écrite.
1. Ecrire deux programmes qui communiquent via un fichier spécial FIFO.
Solution:
Voir fichier fifo_a.c et fifo_b.c.
2. Quel est l’avantage par rapport au pipe du TP précédent ?
2
Solution:
On peut créer des FIFO entre deux processus qui sont déjà indépendants (après le fork).
Les files de messages : msgget, msgsnd, msgrcv
Plus rapide qu’un guichet de la poste !
Les processus peuvent communiquer via une file de message. Les files sont gérées par un module
noyau dédié mettant en file d’attente les messages reçus ou les délivrant sans ordre a contrario des
pipes (Flux de données). Les messages sont une structure avec un type et une donnée textuelle. Ainsi,
on peut filtrer la réception des messages selon le type.
struct mymsg {
long
mtype;
/* message type */
char mtext[MSGSZ]; /* message text of length MSGSZ */
}
Pour récupérer (ou créer) une file de message, il suffit de faire appel à msgget. Pour modifier une
file de message, il suffit de faire appel à msgctl. Pour émettre un message, il suffit de faire appel à
msgsnd. Pour recevoir un message, il suffit de faire appel à msgrcv.
Les émissions/réceptions peuvent être asynchrones ou synchrones.
1. Écrire un programme Server et deux programmes Client tels que le serveur communique de
manière privée et individuelle avec chaque client en n’utilisant qu’une seule file de message.
Les clients listeront les fichiers contenus dans leur répertoire d’exécution (ls -l .), enverront
chaque nom de fichier au serveur qui déterminera si le nom est fun ou pas (l’implémentation de la
fonction fun du serveur est libre).
Solution:
voir server_queue.c et client_queue.c.
3
Téléchargement