Skip to content

Programmation Système - Signaux⚓︎


Définition⚓︎

Les signaux constituent un mécanisme de fondamental de communication entre processus :
Ils sont utilisés par un processus pour signaler à un autre processus (ou à un groupe de processus) l’arrivée d’un événement qui peut être :

– matériel
– lié au fonctionnement multitâche
– lié à une application spécifique

Ce sont des interruptions logicielles !


Exemples de Signaux⚓︎

Liste non exhaustive ...

Nom Fonction
SIGHUP 1 déconnection du terminal
SIGINT 2 interruption ^C
SIGQUIT 3 abandon ^\ (core)
SIGKILL 9 destruction (ne peut être ignoré)
SIGUSR1 10 réservé à l’utilisateur (communication inter-processus)
SIGUSR2 12 réservé à l’utilisateur (communication inter-processus)
SIGPIPE 13 essai d’écriture dans un pipe non ouvert
SIGALRM 14 horloge (arrêt de l’horloge d’un processus: alarm())
SIGTERM 15 terminaison normale d’un processus
SIGCHLD 17 mort d’un fils (envoyé au père)
... ... ...

Tout ces signaux se trouvent dans le fichier header : signal.h

Le comportement par défaut des signaux SIGUSR1 et SIGUSR2 est : SIGKILL !
Si non redéfinis, leur reception entrainera la mort du processus visé ...


Traitements⚓︎

Il y a 3 actions possibles lors de la reception d'un signal par un processus :
- L'ignorance : SIG_IGN
- La prise en compte pour effectuer une action spécifique : nomFonction
- La restauration du comportement par defaut : SIG_DFL

Certains signaux ne peuvent pas être ignorés, par exemple SIGKILL.

Dans le cas d'une action spécifique :
- l’action est faite dans une fonction qui doit être spécifiquement attachée au signal donné.
- cet attachement est valable pour toute la durée du programme.

A l’arrivée du signal :
– le traitement en cours est interrompu
– la fonction est exécutée
– le traitement est repris où il en était avant l'interruption


Primitives⚓︎

Signal⚓︎

La primitive signal() permet de spécifier le comportement d’un processus à la réception d’un signal donné. C'est une fonction non bloquante qu'il faut voir comme une configuration utilisée plus tard, lors de la reception du signal.

1
2
3
4
5
#include<signal.h>
void (*signal (int sig, void (*fcn)(int)))(int)  

- sig : numéro du signal
- (*fcn) : action après réception 

-> Intercepte le signal de numéro sig
-> Exécute la fonction fcn

Exemples⚓︎

1
2
signal(SIGUSR1, traite) ;
signal(SIGINT, SIG_IGN);

Kill⚓︎

La primitive kill() permet d’envoyer un signal à un processus, via son PID.
L’envoi de signal ne peut se faire qu’entre tâches de même UID.
Si on utilise PID = 0 : tous les processus du groupe sont concernés (broadcast).

Elle envoie n'importe quel signal, pas uniquement SIGKILL malgrès son nom !!

1
2
3
4
5
#include<signal.h>
int kill(int pid,int no_signal);  

 pid no du process récepteur
 résultat : 0 si le signal a é envoyé, -1 sinon (erreur)

Exemples⚓︎

1
2
kill (0,SIGUSR1);
kill (1234,SIGKILL);

Pause⚓︎

La primitive pause() correspond à de l’attente pure, d'un signal quelconque. C'est une fonction bloquante.

1
2
3
4
void pause(void);

- Elle ne fait rien
- Attend larrivée dun signal quelconque

Exemple⚓︎

1
pause();

Alarm⚓︎

La primitive alarm() envoi un signal de type SIGALRM au processus appelant après laps de temps (en seconde).
C'est une fonction non bloquante.

1
2
3
4
5
6
7
8
#include<unistd.h>
int alarm (int sec);

- resultat : temps écoulé depuis le dernier appel à alarm();

Note : 
- l'appel à  alarm(0); annule toutes les alarmes enregistrées !
- chaque appel enreigistre une nouvelle alarme, en indiquant en retour le temps restant pour l'alarme précédemment enregistrée.

Exemple⚓︎

1
alarm(12);

Exemple complet⚓︎

Dans le père : Dans le fils :
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <fcntl.h>

int main(void)
{
    int pid ; 
    pid=fork(); 
    if(pid == 0)
        execv("fille", NULL);
    signal(SIGUSR1,fonc); 
    for(;;)
    {
        printf(" je boucle\n ");
        sleep(1); 
    }
}

void fonc(int sig) {
    printf(" signal recu %d\n ", sig);
    exit(0);
}
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <fcntl.h>

int main(void) {
    sleep(5); 
    kill(getppid(),SIGUSR1); 
    exit(0);
}

La position de l'appel à signal() dans le programme est très importante !
La configuration doit être faite avant la reception du signal en question !