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