Programmation Système sous
UNIX
Chapitre 2 : La communication
interprocessus avec des signaux
Najar Yousra
Email : [email protected]
ISI 2 éme ingérieur 2020/2021
Programmation Système sous UNIX
2 éme ing 51
Plan du chapitre
Introduction
Notion de signal
Envoi d’un signal
Traitement d’un signal : signal
Traitement d’un signal : sigaction
Programmation Système sous UNIX
2 éme ing 52
Introduction
Les interruptions logicielles ou signaux sont le mécanisme qui
est utilisé par le système d’exploitation pour aviser les processus
utilisateurs de l’occurrence d’un événement important.
De nombreuses erreurs détectées par le matériel comme
l’exécution d’une instruction non autorisée (comme la division par
0, par exemple) ou l’emploi d’une adresse non valide, sont
converties en signaux qui sont envoyés au processus fautif. Ce
mécanisme permet à un processus de réagir à cet événement sans
être obligé d’en tester en permanence l’arrivée.
Programmation Système sous UNIX
2 éme ing 53
Notion de signal
Sous UNIX, un signal est un événement émis à un processus
ou à un groupe de processus bien identifiés qui :
nom(une constante entière) connu du système< NSIG
Associé à un traitement ou routine
Programmation Système sous UNIX
2 éme ing 54
Notion de signal
Tous les signaux ont une routine de service, ou une action par défaut.
Cette action peut être du type :
A: terminaison du processus
B : ignorer le signal
C: Créer un fichier core
D: Stopper le processus
E : La procédure de service ne peut pas être modifiée
F : Le signal ne peut pas être ignoré
Programmation Système sous UNIX
2 éme ing 55
Notion de signal
Liste alphabétique des signaux sous UNIX
Programmation Système sous UNIX
2 éme ing 56
Notion de signal
Dans le descripteur d’un processus les
champs pour les signaux sont :
Un tableau des signaux émis:(en attente
ou en suspens) un tableau de bits ou de
files de signaux; l’émission d’un signal i
met son bit à 1, son traitement le remet à
0.
Un masque de signaux :un ensemble des
signaux masqués, e.g. un tableau de bits;
Un tableau des traitements des signaux
:e.g. des constantes ou des adresses des
traitants.
Programmation Système sous UNIX
2 éme ing 57
Notion de signal
Pour un processus donné, chaque signal peut être dans les états
suivants (non exclusifs) :
Associé à un traitement :par défaut ou choisi;
masqué(ou bloqué) ou démasqué(débloqué) : traitable ou non
par le processus ;
émis (ou envoyé) à un processus : lorsque l’événement se
manifeste ;cela est noté par le noyau dans le descripteur du
processus ;
en attente: émis, non masqué, pas encore traité ;
en suspens(pending) :émis et masqué, donc pas encore traité.
notifié: délivré à un traitant, en cours de traitement particulier,
traité: ignoré, traité par défaut ou par un traitant particulier
Programmation Système sous UNIX
2 éme ing 58
L’envoi d’un signal
L’émetteur d’un signal peut être :
•le système lui-même,
•un autre processus par kill ou la commande kill,
•le matériel,
•une horloge (timer),
•une touche du terminal de contrôle
Le système peut diffuser un signal à plusieurs processus(groupes)par une
itération de son émission
La notification d’un signal à un processus(mise à jour de son descripteur)est
toujours faite par le système, qui peut recevoir des interruptions du matériel ou
des appels système (kill).
La plupart des systèmes UNIX ne mémorisent au plus qu’une occurrence
pour chaque numéro de signal en suspens :tableau de bits, pas un tableau de files
!(si un signal est émis plusieurs fois avant d’être traité, il ne sera notifié qu’une
seule fois).
Lorsqu’un processus a plusieurs signaux différents en attente, le choix d’un signal
à traiter par le noyau est indéfini :pas de priorité entre les
Programmation signaux.
Système sous UNIX
2 éme ing 59
L’envoi d’un signal
Un processus peut envoyer un signal à un autre.
La commande kill
$ kill – l // liste les signaux
$ kill -nsig npid // Envoi un signal nsig au processus avec le pid
npid
L’appel système kill
Programmation Système sous UNIX
2 éme ing 60
L’envoi d’un signal
Les restrictions sur kill :
• Le signal de numéro 0 n’envoit rien, mais sert à tester l’existence de
processus
•L’émetteur peut envoyer un signal aux processus de la même session (à
ses fils,) ou à des processus d’une autre session, mais appartenant au
même utilisateur.
•L’émetteur ne peut envoyer un signal à un processus d’un autre
utilisateur.=> on ne peut pas utiliser des signaux pour une architecture
client-serveur !
Programmation Système sous UNIX
2 éme ing 61
L envoi d un signal
raise(SIGINT)
Programmation Système sous UNIX
2 éme ing 62
Traitement d’un signal
Sous UNIX, un signal est un événement émis à un
processus ou à un groupe de processus bien
identifiés qui :
nom(une constante entière) connu du système,
un traitant par défaut ou défini par une primitive
système :
- signal(simple, mais rustique), ou mieux par
- sigaction(plus complet).
peut être masqué ou non, signal par signal, Selon
un masque de signaux propre à chaque processus
Programmation Système sous UNIX
2 éme ing 63
Le traitement d’un signal : signal
#include <signal.h>
typedef void (*sighandler_t)(int);
Sighandler_t signal(int signum, sighandler_t handler);
installe le gestionnaire handler pour le signal signum. Handler peut être
SIG_IGN, SIG_DFL ou l'adresse d'une fonction définie par le
programmeur (un « gestionnaire de signal »). Lors de l'arrivée d'un signal
correspondant au numéro signum, un des événements suivants se produit :
* Si le gestionnaire est SIG_IGN, le signal est ignoré.
* Si le gestionnaire est SIG_DFL, l'action par défaut associé à ce signal est
entreprise,
* Si le gestionnaire est une fonction, alors tout d'abord le gestionnaire est
reconfiguré à SIG_DFL, ou le signal est bloqué, puis handler est appelée
avec l'argument signum.
Programmation Système sous UNIX
2 éme ing 64
Le traitement d’un signal : signal
int main(void) int main(void)
{ signal(SIGINT, SIG_IGN); { signal(SIGINT, SIG_DFL);
raise (SIGINT); raise (SIGINT);
sleep (10); sleep (10);
exit(0); exit(0);
} }
void sig_hand(int sig)
{ printf ("singal reçu %d \n",sig);}
int main(void)
{ signal(SIGINT, &sig_hand); raise (SIGINT);
sleep (10);
exit(0);
}
Programmation Système sous UNIX
2 éme ing 65
Le traitement d’un signal : sigaction
La routine sigaction() prend trois arguments et renvoie un entier valant
0 si elle réussit et -1 si elle échoue. Le premier argument : numéro du
signal et les deux autres arguments sont deux pointeurs sur des
structures sigaction. Ces structures définissent le comportement exacte
à adopter lors de la réception d’un signal.
int sigaction(int numero, const struct sigaction * nouvelle, struct sigaction *
ancienne)
- Si le numéro indiqué est inférieur ou égal à 0, supérieur ou égal à NSIG, ou égal à
SIGKILL ou SIGSTOP sigaction( ) échoue.
- Si nouvelle est un pointeur NULL Aucune modification n’a lieu.
- Si ancienne est un pointeur NULL Pas de sauvegarde de l’ancienne routine.
- La structure sigaction est définit dans <sigaction.h> qui est inclus par <signal.h>
Programmation Système sous UNIX
2 éme ing 66
Le traitement d’un signal : sigaction
Nom Type
sa_handler sighandler_t pointeur sur le gestionnaire du signal
void gestionnaire_signal(int numero)
sa_mask sigset_t Un ensemble de signaux: la liste des
signaux à bloquer
sa_flags int contient un ou binaire entre différentes
constantes (configurer le gestionnaire)
Exemples de constante : SA_NOCLDSTOP : concerne SIGCHLD le signal n’est
envoyé que lorsque le fils est définitivement terminé.
- SA_RESTART : les appels système interrompus par le signal seront redémarrés
automatiquement.
- SA_RESTHAND : lorsque cette constante est fournit à sigaction le
comportement par défaut est restoré.
- SA_NODEFER : le signa n’est pas automatiquement bloqué.
Programmation Système sous UNIX
2 éme ing 67
Le traitement d’un signal : sigaction
Quelques commandes de manipulation de masques de signaux :
int sigemptyset (sigset_t * ensemble) ; //initialiser l’ensemble sans aucun
signal bloqué
int sigfillset (sigset_t * ensemble) ; //initialiser l’ensemble avec tous les
signaux du système bloqués
int sigaddset (sigset_t * ensemble, int numero_signal) ; //ajouter un signal à
un ensemble pour qu’il soit bloqué.
int sigdelset (sigset_t * ensemble, int numero_signal) ; // éliminer un signal
d’un ensemble.
int sigismember (sigset_t * ensemble , int numero_signal) ;//permet de savoir
si un signal appartient à un ensemble ou pas (1 si c le cas)
Programmation Système sous UNIX
2 éme ing 68
Primitive sigprocmask
La primitive sigprocmask
La primitive permettant de mettre en place un masque de signaux, c'est à dire, un
ensemble de signaux bloqués, s'appelle sigprocmask, nous donnons ici son
prototype :
int sigprocmask(int mode, const sigset_t *ens, sigset_t *anciens)
Passons en revue les trois paramètres de cette fonction : Code de retour0 si tout
s'est bien passé, -1 sinon
Mode : Ce paramètre définit le type de mise en place du masque spécifié par ens.
En effet, il est possible de :
- Remplacer le masque existant : mode=SIG_SETMASK :
- ajouter au masque existant les signaux de ens : mode=SIG_BLOCK.
-Retirer au masque existant les signaux de ens : mode=SIG_UNBLOCK
Ens : Ensemble des signaux définissant un nouveau masque
Anciens : A moins que ce paramètre ne soit nul, la structure sigset_t pointée
contiendra au retour la liste des signaux qui étaient bloqués avant l'opération.
Cette fonctionnalité offerte par sigprocmask est très intéressante car elle
permettra, par exemple, de remettre en place l'ancien masque
Programmation à sous
Système la sortie
UNIX de votre
section critique. 2 éme ing 69
Primitive sigpending
Récupérer la liste des signaux pendants bloqués
La primitive suivante permet de connaître la liste des signaux
pendants et bloqués. N'oubliez pas que si vous les débloqués, la
primitive de gestion sera immédiatement appelée !
int sigpending(sigset_t *ens)
A l'instar des autres primitives opérant sur les
signaux, sigpending renvoie
0 si tout s'est déroulé convenablement — auquel cas, la structure
pointée par ens contient la liste des signaux bloqués et pendants,
liste qu'il conviendra de traiter, par exemple, avec sigismenber
et -1 dans tous les autres cas.
Programmation Système sous UNIX
2 éme ing 70
Le traitement d’un signal : exemple 1
void sig_hand(int sig)
{ printf ("signal reçu %d \n",sig);}*
int main(int argc, char **argv)
{sigset_t sig_proc;
struct sigaction action;
sigemptyset(&sig_proc); /* changer le traitement */
action.sa_mask=sig_proc;
action.sa_flags=0;
action.sa_handler = sig_hand;
sigaction(SIGINT, &action,0);
/* masquer SIGINT */
sigaddset (&sig_proc, SIGINT);
sigprocmask (SIG_SETMASK,&sig_proc, NULL);
exit(0);}
Programmation Système sous UNIX
2 éme ing 71
Le traitement d’un signal : exemple 2
Programmation Système sous UNIX
2 éme ing 72
Le traitement d’un signal : exemple 3
Programmation Système sous UNIX
2 éme ing 73
Temporisation // attente d’un
signal
Les appel système sleep() et pause() peuvent être utiles lorsqu’on travaille
avec des signaux.
#include <unistd.h>
int pause(void);// permet de mettre le processus courant en attente de l’arrivée
de signaux.
int sleep(unsigned int seconds);// permet de bloquer (état endormi) le processus
courant sur la durée passée en paramètre.
Programmer un réveil pour l'émission d'un signal.
#include <unistd.h>
unsigned int alarm(unsigned int nb_sec);
alarm programme une temporisation pour qu'elle envoie un
signal SIGALRM au processus en cours dans nb_sec secondes. Si le signal
n'est pas bloqué ou intercepté, sa réception terminera le processus.
Si nb_sec vaut zéro, aucune alarme n'est planifiée. Dans tous les cas,
l'appel alarm annule l'éventuelle programmation précédente.
Programmation Système sous UNIX
2 éme ing 74
Exemple temporisation
Programmation Système sous UNIX
2 éme ing 75