From 9abcf5b28c49e96b3b87e8109f372e8f2d5af4bb Mon Sep 17 00:00:00 2001 From: sebastien faucou <sebastien.faucou@univ-nantes.fr> Date: Tue, 7 Dec 2021 22:35:40 +0100 Subject: [PATCH] ajout du tp4 sur les signaux. --- tp4/tp4.md | 134 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 tp4/tp4.md diff --git a/tp4/tp4.md b/tp4/tp4.md new file mode 100644 index 0000000..b47bd03 --- /dev/null +++ b/tp4/tp4.md @@ -0,0 +1,134 @@ +# Introduction + +## Appels systèmes et fonctions utiles + +En plus des informations disponibles dans le support de cours et dans +vos notes, on trouve un panorama du fonctionnement des signaux UNIX dans +la page `signal(7)` du manuel en ligne. Des explications complémentaires +concernant la sûreté de certaines fonctions et appels systèmes +lorsqu'ils sont appelés depuis un gestionnaire de signal sont données +dans la page `signal-safety(7)`. Enfin, les fonctions suivantes +disposent également de pages dédiées dans le manuel : + + - `sigaction` : installer un gestionnaire de signal? + - `sigprocmask` : changer le masque des signaux bloqué par le + processus. + - `sigemptyset`, `sigfillset`, `sigdelset`, `sigaddset` : créer et + manipuler un masque de signaux. + - `sigsuspend` : met le processus appelant en pause jusqu'à l'arrivée + d'un signal parmi un ensemble sélectionné par un masque. + - `kill` : envoyer un signal à un processus. + - `pause` : met le processus appelant en attente d'un signal. + +# Travail à réaliser + +## Variables volatiles et mises à jour atomiques + +``` c +#include <stdio.h> +#include <stdlib.h> +#include <signal.h> +#include <string.h> + +int exit_flag = 0; + +void handler(int sig) { + exit_flag = 1; +} + +int main(void) { + struct sigaction action; + + memset(&action, '\0', sizeof(action)); + action.sa_handler = handler; + sigaction(SIGTERM, &action, NULL); + + while (!exit_flag); + + printf("End.\n"); + exit(EXIT_SUCCESS); +} +``` + +L'exercice porte sur le programme ci-dessus. + +1. Comment peut-on faire en sorte que le programme sorte de la boucle, + affiche le message `"End.\n"` et se termine ? +2. Compiler le programme à l'aide de la commande suivante : `gcc -Wall + -O0 <nomfichier.c> -o <nomprog>` et vérifier votre réponse à la + question précédente. +3. Même question en utilisant la commande `gcc -Wall -O2 <nomfichier.c> + -o <nomprog>`. Commenter. +4. Corriger le programme en conséquence. Pour cela, il sera utile de se + renseigner sur le mot-clé `volatil` et le type `sig_atomic_t`. + +## Masques et signaux bloqués + +Soit un programme conforme à la spécification suivante. Pour commencer, +le programme installe un gestionnaire pour le signal `SIGCHLD`. +Lorsqu'il est appelé, ce gestionnaire passe la variable globale `go` à +`1`. Ensuite, le programme se clone. Le processus enfant bloque tous les +signaux puis entre dans une boucle infinie. Le processus parent entre +dans une boucle dont il sort lorsque la variable `go` vaut `1`. Il +attend ensuite la terminaison du processus enfant, dont il affiche la +cause et le cas échéant, le signal responsable. + +1. Est-il possible de faire se terminer le processus enfant ? +2. Écrire le programme et vérifier votre réponse à la question + précédente. + +## Interruption des appels systèmes + +``` c +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <signal.h> +#include <string.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <unistd.h> + +static volatile sig_atomic_t counter = 0; + +void handler(int sig) +{ + counter ++; + return; +} + +int main(void) +{ + struct sigaction action; + pid_t pid; + int i; + + memset(&action, '\0', sizeof(action)); + action.sa_handler = handler; + sigaction(SIGUSR1, &action, NULL); + + pid = fork(); + + if (pid == 0) + { + for(i = 0; i < 42; i++) + { + kill(getppid(), SIGUSR1); + printf("signal sent %d times to parent\n", i+1); + } + } + else + { + wait(NULL); + printf("final value: %d\n", counter); + getchar(); + } + exit(0); +} +``` + +1. Sans exécuter le programme ci-dessus, expliquer ce qu'il fait. +2. Compiler le programme, l'exécuter et vérifier votre réponse à la + question ci-dessus. +3. Corriger le problème (un indice est donné dans le titre de + l'exercice). -- GitLab