7.1 KiB
title | categories | tags | date | |||||
---|---|---|---|---|---|---|---|---|
Les 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 ouCRTL + 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 d’arrê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 d’arrê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 à modifierhandler
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