cours/content/progsys/4_les-signaux/index.md

7.1 KiB
Raw Blame History

title categories tags date
Les signaux
Programmation système
cours
C
programmation
signaux
2018-09-25

En programmation système, un signal est une notification à un processus qu'un évènement a eu lieu. Également appelés Interruptions Logicielles, les signaux son asynchrone est il est impossible de prédire à quel moment il arriveront.

Les signaux couvrent plusieurs types d'évènements :

  • Les actions utilisateurs CTRL + C pour SIGINT ou CRTL + Z pour SIGSTOP
  • Les fautes matérielles comme la division par zéro SIGFPE, la référence mémoire invalide SIGSEGV, écriture mémoire erronée SIGSEGV etc.
  • les fautes logicielles comme l'erreur d'écriture dans un tube SIGPIPE, la notification urgente de données disponibles SIGURG, l'alarme SIGALRM

Ils représentent une forme basique de communication inter-processus ( IPC ) mais permettent aussi à l'utilisateur d'intervenir dans le déroulement d'un processus. (voir man 1 kill et man 2 kill).

C'est au processus de se déclarer à l'écoute d'un type d'évènement en initialisant un gestionnaire appelé lorsque l'évènement visé aura lieu. Lorsque ce dernier a lieu, le gestionnaire est appelé avec toutes les informations nécessaires. A la fin de l'exécution du gestionnaire, l'exécution du processus reprend normalement à l'endroit ou elle s'est arrêtée.

Comportement associés aux signaux.

Par défaut, des comportements sont associés aux signaux :

  • stop : arrête le processus
  • cont : continuer le processus s'il est arrêté.
  • term : terminer le processus
  • ign : ignorer le processus
  • core : créer un fichier core (contexte d'exécution du processus) puis sigterm

Liste des signaux

Norme POSIX 1-1999

Signal Valeur Action Commentaire
SIGHUP 1 Term Déconnexion du terminal ou fin du processus de contrôle
SIGINT 2 Term Interruption depuis le clavier CTRL + C
SIGQUIT 3 Core Demande ”Quitter” depuis le clavier CTRL + \\
SIGILL 4 Core Instruction illégale
SIGABRT 6 Core Signal darrêt depuis abort(3)
SIGFPE 8 Core Erreur mathématique virgule flottante
SIGKILL 9 Term Signal ”KILL”
SIGSEGV 11 Core Référence mémoire invalide
SIGPIPE 13 Term Écriture dans un tube sans lecteur
SIGALRM 14 Term Temporisation alarm(2) écoulée
SIGTERM 15 Term Signal de fin
SIGUSR1 10 Term Signal utilisateur 1
SIGUSR2 12 Term Signal utilisateur 2
SIGCHLD 17 Ign Fils arrêté ou terminé
SIGCONT 18 Cont Continuer si arrêté
SIGSTOP 19 Stop Arrêt du processus
SIGTSTP 20 Stop Stop invoqué depuis le terminal CTRL + Z
SIGTTIN 21 Stop Lecture sur le terminal en arrière-plan
SIGTTOU 22 Stop Écriture dans le terminal en arrière-plan

Les signaux SIGKILL et SIGSTOP ne peuvent ni être capturés ou ignorés.

Normes SUSv2 et POSIX 1-2001

Signal Valeur Action Commentaire
SIGBUS 7 Core Erreur de bus (mauvais accès mémoire)
SIGPOLL Term Événement ”pollable”, synonyme de SIGIO
SIGPROF 27 Term Expiration de la temporisation pour le suivi
SIGSYS 31 Core Mauvais argument de fonction
SIGTRAP 5 Core Point darrêt rencontré
SIGURG 23 Ign Condition urgente sur socket
SIGVTALRM 26 Term Alarme virtuelle
SIGXCPU 24 Core Limite de temps CPU dépassée
SIGXFSZ 25 Core Taille de fichier excessive
SIGWINCH 28 Ign Fenêtre redimensionnée

Le core dump

Un core dump est une image mémoire d'un processus prise au moment d'un plantage. Elle contient des information utiles pour l'analyse du crash :

  • copie de la mémoire au moment du plantage
  • statut de terminaison du processus
  • copie des registres CPU

Prenons l'exemple de code suivant :

int main ()
{
    int a = 10;
    int b = 0;
    a = a / b
}

Compilons le et exécutons le :

$ gcc -g -Wall sigfpe.c -o sigfpe
$ ./sigfpe
[2] 8112 floating point exception (core dumped) ./sigfpe

Analysons maintenant le core dump avec gdb

$ gdb sigfpe core
GNU gdb (Debian 7.11.1-2) 7.11.1
Core was generated by `./sigfpe'.
Program terminated with signal SIGFPE, Arithmetic exception.
#0 0x00000000004004ec in main () at sigfpe.c:4
4       a = a / b;
(gdb) backtrace full
#0 0x00000000004004ec in main () at sigfpe.c:4
    a = 10
    b = 0
(gdb)

Gestion des signaux.

en programmation système, la gestion des signaux revient à changer le comportement par défaut par un souhaité lors de la réception d'un signal donné par un processus.

#include <signal.h>

typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
  • signum est le numéro de signal à modifier
  • handler vaut soit SIG_IGN pour ignorer le signal, soit SIG_DFL pour le réinitialiser à sa valeur par défaut ou est un pointeur vers une fonction à appeler.

L'appel à signal() renvoie la valeur du gestionnaire de signal précédent en cas de réussite, sinon SIG_ERR.

exemple de code

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>

void sigusr1_trigger() {
    write(1, "SIGUSR1 received\n", 17);
}

int main () {
    if (signal(SIGUSR1, sigusr1_trigger) == SIG_ERR) {
        perror("Unable to catch SIGUSR1\n");
    }
    else {
        printf("SIGUSR1 is catched on process with PID=%d\n", getpid());
    }
    for(;;) {
        sleep(10);
    }
}

Exécution

1 sur le premier terminal
$ ./sigusr1
SIGUSR1 is catched on process with PID=10333
2 Sur le second terminal, envoi du signal :
$ kill -USR1 10333`
3 Retour sur le premier terminal :
$ ./sigusr1
SIGUSR1 is catched on process with PID=10333
SIGUSR1 received

Envoyer des signaux

Des signaux peuvent être envoyés à d'autres processus avec kill() ou au processus en cours avec raise().

include <signal.h>

int kill(pid_t pid, int sig);
int raise(int sig);

Ces deux fonctions renvoient 0 en cas de succès, sinon -1.

Il est aussi possible de bloquer le processus courant et d'attendre un signal avec la fonction pause()

int pause(void);

En cas d'erreur, retourne -1 avec errno positionné à EINTR

Poser une alarme

Un processus peut définir une alarme qui aboutira à l'envoi d'un signal SIGALRM au bout d'un temps défini. Il n'est cependant possible de ne définir qu'une seule alarme par processus.

#include <unistd.h>

unsigned int alarm(unsigned int seconds);

Il est aussi possible d'annuler une alarme précédemment définir avec alarm(0).

Bibliographie

Présentation support de cours