Laboratoire 10 - Signaux et tubes
Remarque: n’oubliez pas, lors de l’utilisation d’appels système, de traiter les cas d’erreur.
Modification du gestionnaire d’un signal
- On veut gérer le signal d’interruption de processus (signal
SIGINT
). Attention, il faut que l’arrêt du processus reste possible, par un autre moyen. Pour ce faire, créez un programmep0
permettant d’essayer les diverses possibilités de gestion d’un signal et constatez qu’il est possible de:
- gérer directement le signal, en affichant le texte
Réception du signal SIGINT
dans le gestionnaire montrant que le signal a bien été capturé et que l’on maîtrise la situation, - ignorer l’occurrence du signal,
- traiter une fois le signal, puis de revenir au traitement du signal par défaut par défaut,
- traiter deux fois le signal, puis de revenir au traitement du signal par défaut par défaut.
-
Comment peut-on vérifier qu’un signal n’est pas réceptionné autant de fois qu’il est envoyé ?
-
Reprenez le programme
p0
et modifiez-le afin de capturer le signalSIGUSR1
. Lorsque ce signal est capturé, effectuez une boucle de 5 itérations; à chaque itération affichez le messageItération <numéro d'itération> pour la gestion du signal <numéro du signal>
. -
Que se passe-t-il si le programme
p0
reçoit le signalSIGINT
durant le traitement d’un signalSIGUSR1
? Pourquoi ? -
Modifiez le programme
p0
de sorte que l’exécution de la gérante du signalSIGUSR1
ne puisse être interrompue lors de la réception du signalSIGINT
. -
Noter, les fonctions et appels systèmes suivant vous seront utiles:
sigaction
,sigemptyset
,sigaddset
Tubes shell
- Créez un programme
shellpipe
qui prend comme argument deux commandes séparées par le symbole seul+
et qui exécute ces deux commandes en dirigeant la sortie de la première vers l’entrée de la seconde.
$ ./shellpipe ls / + wc -l
shellpipe
doit attendre que les deux commandes terminent. Le programme retourne le code de retour de la dernière commande.
Extra: Redirection de processus
Cet exercice implémente la substitution de processus (<()
) du shell bash
.
Implémentez shellfifo.c
, qui prend deux commandes séparées par "<|"
et où l’argument "{}"
de la première commande est substitué par le chemin d’un fichier tube nommé fifo
dont le bout en écriture est connecté à la sortie standard de la seconde commande.
$ echo "Hello" > hello
$ echo "Goodbye" > bye
$ ./shellfifo wc hello "{}" bye "<|" echo Bonjour le monde
1 1 6 hello
1 3 17 fifo
1 1 8 bye
3 5 31 total
C’est +/- équivalent en shell bash à <()
sauf que "{}"
et "<|"
sont beaucoup plus faciles à traiter que la syntaxe bash.
$ wc hello <(echo "Bonjour le monde") bye
1 1 6 hello
1 3 17 /dev/fd/63
1 1 8 bye
3 5 31 total
Attention:
- L’entrée standard des deux commandes reste inchangée (on laisse 0 tranquille!)
shellfifo
doit attendre que les deux commandes terminent et retournent le code de retour de la premièreshellfifo
ne laisse pas trainer des fichiers fifo non plus- Normalement, il faudrait créer le fichier fifo dans
/tmp/
avec un nom unique, voir par exemplemkdtemp(3)
. Pour l’exercice, appelez juste votre fichierfifo
dans le répertoire courant. - Les fonctions et appels systèmes
mkfifo
etdup2
vous seront utiles.
Bonus: Redirection Version 2
Ajouter une option -p
qui, au lieu d’un tube nommé, utilise à la place un tube anonyme et un chemin de pseudo tube /proc/self/fd/XX
. C’est en fait l’implémentation du shell bash sous Linux quand /proc
est disponible.
Par exemple:
$ ./shellfifo -p wc hello "{}" bye "<|" echo Bonjour le monde
1 1 6 hello
1 3 17 /proc/self/fd/3
1 1 8 bye
3 5 31 total