Laboratoire 10 - Signaux et tubes

Sommaire

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 programme p0 permettant d’essayer les diverses possibilités de gestion d’un signal et constatez qu’il est possible de:
  1. 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,
  2. ignorer l’occurrence du signal,
  3. traiter une fois le signal, puis de revenir au traitement du signal par défaut par défaut,
  4. 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 signal SIGUSR1. Lorsque ce signal est capturé, effectuez une boucle de 5 itérations; à chaque itération affichez le message Ité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 signal SIGINT durant le traitement d’un signal SIGUSR1 ? Pourquoi ?

  • Modifiez le programme p0 de sorte que l’exécution de la gérante du signal SIGUSR1 ne puisse être interrompue lors de la réception du signal SIGINT.

  • 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ère
  • shellfifo 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 exemple mkdtemp(3). Pour l’exercice, appelez juste votre fichier fifo dans le répertoire courant.
  • Les fonctions et appels systèmes mkfifo et dup2 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