chapitre 6 : gestion des...
TRANSCRIPT
1
Chapitre 6 : Gestion des signaux
Version Octobre 2012 N°288
Pour commencer… (1)
Deux types de communication
Synchrone (plus facile à programmer)
Processus décide du moment de la communication
Mise en attente possible
Appel systèmes (IPC, tubes, Sockets)
Asynchrone
Programmation événementielle
plusieurs formes : interruption, signal, événement
graphique, exception
Lisibilité?, perte évènements,…
2
Version Octobre 2012 N°289
Pour commencer… (2)
A quoi sert un signal ?
Indiquer à un processus l’arrivée d’un évènement
Faire exécuter un traitement à un processus
D’où vient un signal ?
Du noyau
D’un autre processus
Qui délivre un signal ?
Le noyau
Qui décide de la réaction à un signal ?
Le processus (mais quelques contraintes)
Version Octobre 2012 N°290
Classification des signaux
Fin d'un processus
Exceptions (processus): hors adressage, ...
Etat irrécupérables (appels systèmes): espace ‘dépilé‘
Erreur inattendue (appels systèmes)
Signaux (processus en mode utilisateur)
Interaction avec le terminal
Mise au point des processus
Système V/POSIX : 19 signaux
Origine: processus ou interne
3
Version Octobre 2012 N°291
Principaux signaux
différent sur alpha & sparc, i386 & ppc, mips ?
SIGCHLD : ignoré par défaut
SIGXFSZ : pas POSIX.1
Signal Numéro Signification
SIGHUP 1 liaison coupée / relecture fichier de configuration
SIGINT 2 Interruption / CTRL-C au clavier
SIGQUIT 3 Quit
SIGFPE 8 Erreur calcul en virgule flottante (division par zéro)
SIGKILL 9 Tuer le processus (non interceptable)
SIGSEGV 11 violation de segment (en général pointeur nul)
SIGSYS 12 Paramètre Invalide (appel système)
SIGPIPE 13 Écriture dans un tuyau qui n'a plus de lecteurs
SIGALRM 14 Alarme (chronomètre)
SIGCHLD 20,17,18 Indique au processus père la terminaison d’un fils
SIGXFSZ 25,25,31 Taille de fichier supérieure à la limite
SIGUSR1 30,10,16 Signal utilisateur 1/2
Version Octobre 2012 N°292
Quelques précisions…
Action par défaut : Termine le processus : SIGHUP, SIGINT, SIGKILL, SIGUSR1/2, SIGPIPE, SIGALARM, SIGTERM, … Termine + core : SIGQUIT, SIGILL, SIGTRAP, SIGBUS, SIGSEGV, SIGXCPU, SIGXFSZ, … Ne fait rien : SIGCHLD, SIGURG, … Interrompt le processus : SIGSTOP, SIGTTIN, SIGTTOU, SIGTSTP
Contraintes SIGKILL/SIGSTOP: ne peut être intercepté SIGKILL/SIGSTOP: ne peut être ignoré/bloqué
(Signaux: Non POSIX)
4
Version Octobre 2012 N°293
Liste des signaux (1)
Version Octobre 2012 N°294
Liste des signaux (2)
5
Version Octobre 2012 N°295
Classification des signaux (1)
Signaux de terminaison
Version Octobre 2012 N°296
Classification des signaux (2)
Réveils par horloge + gestion des tâches
6
Version Octobre 2012 N°297
Classification des signaux (3)
Gestion du système, périphériques
Version Octobre 2012 N°298
Classification des signaux (4)
matériel, « logique », obsolètes
7
Version Octobre 2012 N°299
Appartenance à une norme (1)
SIGABRT, SIGALRM, SIGCHLD, SIGCONT, SIGFPE, SIGHUP, SIGILL, SIGINT
Version Octobre 2012 N°300
Appartenance à une norme (2)
SIGKILL, SIGPIPE, SIGQUIT, SIGSEGV, SIGSTOP, SIGTERM
8
Version Octobre 2012 N°301
Appartenance à une norme (3)
SIGTSTP, SIGTTIN, SIGTTOU, SIGUSR1, SIGUSR2
Version Octobre 2012 N°302
Principes de base
Structures de mémorisation : d’un signal (table des processus)
du comportement (zone utilisateur)
du masquage d’un signal
Principes fondamentaux : Fonctionnement comme une interruption
Pas de mémorisation du nombre d'occurrences
Traitement du signal:
Mode noyau Mode utilisateur Mode noyau:
Pas d'action immédiate
Principales fonctionnalités : envoyer un signal, définir un comportement, retarder l’arrivée d’un signal…
9
Version Octobre 2012 N°303
Intégration dans un processus
Table des Processus
Processus 2
Processus 1
…
1 2 31
Handler1(){…} Handler2(){…} main(){…}
PID: xxxx
0
…
1 2 31
Spécification du comportement
Réception du signal
0/1 0/1/offset
Masquage de singaux
…
1 2 31
0/1
Version Octobre 2012 N°304
Processus et signaux : compléments
L'appel fork préserve les comportements des signaux (et le groupe du processus)
Les appels exec remettent les comportements des Signaux à SIG_DFL sauf pour les signaux ignorés avant le exec.
Traitement du signal SIGCHLD différent: Réveil d'un processus endormi
Voir la famille d’appels systèmes wait
10
Version Octobre 2012 N°305
Gestion du groupe d’un processus (1)
Un processus peut consulter/modifier son groupe
Ne pas confondre avec le groupe de l’utilisateur
Utilisé dans le shell (lancement de la commande)
Appels systèmes:
int setpgid (pid_t pid, pid_t pgid);
Le groupe de pid devient pgid
pid_t getpgid (pid_t pid);
Lecture du groupe du processus pid
int setpgrp (void);
Obsolète: le groupe du processus courant devient
« numéro du processus courant »
pid_t getpgrp (void);
Obsolète: le groupe du processus courant
Version Octobre 2012 N°306
Gestion du groupe d’un processus (2)
#include <signal.h>
int main () {
setpgrp();
...
fork ();
...
printf ("groupe = %d", getpgrp());
...
}
ou setpgid(0,0)
ou getpgid(0)
11
Version Octobre 2012 N°307
Gestion du groupe d’un processus (3)
Table des Processus
1003
1040
…
1055
1065
1003
1003
1003
1003
PID PGID 1003
1065
1055 1040
bash
fork
fork
fork
fork
Tout processus peut changer son groupe
Pouvoir envoyer un signal à un groupe
Version Octobre 2012 N°308
Signal: se préparer à recevoir un signal
signal
Traitement par défaut (SIG_DFL) Ignorer le signal (SIG_IGN) Nom du « handler » ou « signal catching function » Pas de parenthèses sous linux et UNIX V7: l’association est valable une fois sous BSD: association permanente
traitement
N°signal
Une première fonction…
12
Version Octobre 2012 N°309
Traiter l’arrivée d’un signal (1)
signal (numéro, SIG_DFL)
signal (numéro, SIG_IGN)
signal (numéro, routine)
Attention au code réentrant (ex: printf) Variable(s) partagée(s) si plusieurs threads
Version Octobre 2012 N°310
Traiter l’arrivée d’un signal (2)
Masquage éventuel de signaux (signal traité?)
S’interroger sur le signal + infos (siginfo)
Traitement
Analyser la cause (errno…), communiquer…
Démasquage éventuel
(Re) positionnement éventuel du signal
Terminer :
Quitter le processus (exit)
Retourner au point d’interruption (return)
Se positionner ailleurs – gestionnaire spécialisé
(sig)(long|set)jmp Lieu interruption: inst. Ordinaire ou Ap. Sys.
13
Version Octobre 2012 N°311
signal: exemple simple
#include <signal.h>
void capture (int sig) { printf(``Signal reçu %d\n'', sig); }
int main () {
signal (SIGINT, capture);
...
while (1) { printf(``Hello World!\n''); sleep(1); }
}
Détourner CTRL-C
Remise à zéro de la capture: Oblige à recapturer.
Version Octobre 2012 N°312
Signal: exemple plus complexe
#include <signal.h> int main () { int pid, res, etat; signal (SIGCHLD, hello); for (i=0; i<3; i++) { if ( (pid = fork()) == 0) { signal (SIGCHLD, SIG_IGN); ... exit (1) } else ... } res = wait (&etat); ... }
14
Version Octobre 2012 N°313
kill: envoyer un signal
kill (pid, signal) : au processus n°pid kill (-pid, signal) : à tous les processus du groupe n°pid kill (0, signal) : à tous les processus du même groupe kill (-1, signal) : à tous les processus (propriétaire/tous) sauf : swapper (0), init (1) et le processus lui-même
Processus cible
N°signal
SUID, EUID peut être différent mais RUID identique
Version Octobre 2012 N°314
Envoyer un signal (compléments)
Qui envoie ?
un processus
tout signaux peut être envoyé
cas d’une touche / shell
le noyau, le matériel
Une horloge
Notification: toujours le système, pas de priorité
MAJ infos processus
Signaux - cas particuliers
SIGCONT (même session)
« 0 » pour tests processus
15
Version Octobre 2012 N°315
kill: exemple simple
#include <signal.h>
capture (int s) {...}
...
int main () { /* Processus 1 */ signal (SIGINT, hello); ...
}
int main () { /* Processus 2 */ kill (pid, SIGINT); kill (0, SIGINT); kill (-1, SIGINT); (*)
...
} (*): pour root Protection: euid/uid (émetteur) = euid/uid (récepteur)
Version Octobre 2012 N°316
Informations sur un signal
Affichage message +
nom
Nb signaux
Tableau nom des signaux
Nombre de signaux sur le système utilisé 48 (OSF1), 45 (SOLARIS), 32 (LINUX) psignal ≈ perror psignal: pas POSIX (voir signal.h)
16
Version Octobre 2012 N°317
Envoi d’un signal sur soi-même
N° signal
S’envoyer un signal ≈ kill ( getpid(), signo) section 3 (C-ANSI)
S’envoyer SIGABRT ≈ kill ( getpid(), SIGABRT) Ne pas terminer le handler par return vidage mémoire (fichier core)
Version Octobre 2012 N°318
Gestion du temps (1)
ITIMER_REAL
ITIMER_VIRTUAL
ITIMER_PROF
temps réel externe (montre). temps virtuel du processus seul (temps CPU). temps virtuel complet du processus (temps CPU + des appels systèmes).
SIGPROF + SIGVTALRM : principalement par les outils de profilage (estimation du temps passé dans les différentes parties d’un programme.
1μ sec
[ SIGALRM] [ SIGVTALRM] [ SIGPROF]
0
fréquence Val. restante
sec. μsec. sec. μsec. ≠0: actif 0: inactif
+t
f(système) ≈ 10ms
17
Version Octobre 2012 N°319
Gestion du temps (2) ITIMER_REAL
ITIMER_VIRTUAL ITIMER_PROF
(*): seule la fréquence est nécessaire (**): avant réinitialisation
Nouv. Valeur (*)
¬NULL
sauvegarde (**)
¬NULL valeur
retournée
Version Octobre 2012 N°320
Gestion du temps (3)
Fréquence en secondes
≈ setitimer ( ITIMER_REAL, itermerval) mesure grossière (ok si machine chargée) ualarm (micro secondes, secondes)
18
Version Octobre 2012 N°321
Faire attendre un processus
Mise en attente du processus (jusqu’à réception signal) Ne gaspille pas le CPU Attention: pas de masquage des signaux
Attente active bornée ou pas For (;;;) ou for (i=xxx, i > 0, i--) mauvaise utilisation CPU
Handler: • return : process continue • exit : process se termine SIG_DFL: termine
Passive + bornée : • sleep • nanosleep
Passive + non bornée
Version Octobre 2012 N°322
nanosleep: Attente bornée
Très loin des nanosecondes: mais 1 à 10 millisecondes rem ¬NULL : durée restante au réveil
Temps d’attente
résultat
19
Version Octobre 2012 N°323
Insuffisance de signal: exemples (1)
Mettre en attente tant qu’un signal n’arrive pas Non atomicité du traitement Le processus reste bloqué si un seul signal
Réception du signal
sleep(n) : « attendre » n secondes sauf si un signal est reçu
Version Octobre 2012 N°324
Insuffisance de signal: exemples (2)
Le processus reste bloqué
Réception du signal
Implémenter sleep (3)
20
Version Octobre 2012 N°325
Insuffisance de signal: exemples (3a)
Utiliser setjmp et longjmp pour assurer qu’il n’y a pas de blocages les conditions de vitesse le retour de longjmp peut faire échouer un autre handler qui serait interrompu par SIGALRM
Implémenter sleep (3)
Sauvegarde de l’environnement avant « alarm »
Restauration environnement
Version Octobre 2012 N°326
Insuffisance de signal: exemples (3b)
sortie très incertaine
Implémenter sleep (3)
21
Version Octobre 2012 N°327
Handlers et la réetrance (1)
Appel système / fonction réentrant(e)
Un handler est considéré comme valide si : un appel système ou une fonction s’exécute il/elle est interrompu(e) par la réception d’un signal le handler appelle cet(te) appel système/fonction Et : le résultat du handler est correct le résultat de l’appel système/fonction est correct
Appel système / fonction non réentrant si interruptible utilise la mémoire du processus
bss, data, heap ( malloc, free + leurs utilisateurs) Primitives C-ANSI d’E/S: printf, getchar…
Version Octobre 2012 N°328
Handlers et la réetrance (2)
Primitives garanties réentrantes
22
Version Octobre 2012 N°329
Handlers et la réetrance (3)
Primitives non interruptibles (rapides , E/S sur le disque) N’utilisent pas la mémoire du processus pour le résultat
Primitives garanties réentrantes
Version Octobre 2012 N°330
Se préparer à recevoir un signal évolution
• signal: mécanisme non fiable Atomicité ? possibilité de masquage ? Comportement ?
1ère évolution : SVRX : sigset, sighold, sigrelse, sigignore, sigpause BSD4.X : sigvec, sigblock, sigsetmask, sigpause,
2ème évolution (POSIX) : un mécanisme de signaux fiables, avec masquage possible : sigaction : associer handler/signal + masquage atomique ; sigprocmask : connaître ou modifier le masque ; sigpending : connaître les signaux en suspens ; sigsuspend : mettre le processus en attente + démasquage atomique.
23
Version Octobre 2012 N°331
sigaction: se … à recevoir un signal
comportement
N°signal
Une deuxième fonction…
Sauvegarde comportement
Le numéro du signal auquel on souhaite réagir. Un pointeur sur une structure de type sigaction.
Comportement relatif à la réception du signal
Un pointeur résultat : si ¬NULL ancienne configuration de traitement du signal.
Association handler/signal perdure (prochain appel)
Version Octobre 2012 N°332
Struct sigaction: champs intéressants
struct sigaction { void (* sa_handler) (int); sigset_t sa_mask; int sa_flags; }
SIG_DFL,SIG_IGN,pointeur
Tableau des signaux bloqués Options liées à la gestion d’un signal
sigemptyset(sigset_t m) SA_RESTART, SA_RESETHAND
SA_ONESHOT ou SA_RESETHAND : Rétablir l'action à son comportement par défaut.
24
Version Octobre 2012 N°333
Gestion du blocage d’un signal (1)
Signal à masquer
Masquer tout
Initialisation du tableau pour sigaction Partir d’un tableau vide et ajouter des signaux à bloquer Faire l’inverse…
Signal à ne pas masquer
Intialisation
Version Octobre 2012 N°334
#include <signal.h>
macros SIG_* et sig*
int sigemptyset (sigset_t *set);
Initialisation du tableau à ‘0’
int sigfillset (sigset_t *set);
Initialisation du tableau à ‘1’
int sigaddset (sigset_t *set, int signum);
Initialisation de la case signum du tableau à ‘1’
int sigdelset (sigset_t *set, int signum);
Initialisation de la case signum du tableau à ‘0’
int sigismember (const sigset_t *set, int signum); Est-ce que la case signum du tableau est initialisée à ‘1’
Gestion du blocage d’un signal (2)
réentrantes
Type abstrait
25
Version Octobre 2012 N°335
Gestion du blocage d’un signal (3)
Signal masqué?
Signaux masqués
signo dans set ?
Par rapport à sigaction:
act.sa_mask: ajoutés avant appel du handler act.sa_mask: démasqués au retour du handler Le signal associé au handler: masqué implicitement
Rajouté au tableau
Version Octobre 2012 N°336
#include <signal.h>
…
void capture (int sig) { printf(``Signal reçu %d\n'', sig); }
int main() {
struct sigaction act;
act.sa_handler = capture;
sigemptyset(&act.sa_mask);
act.sa_flags=0;
sigaction(SIGINT, &act, 0);
while (1) { printf(``Hello World!\n''); sleep(1); }
}
sigaction: exemple simple
pas de « () »
pas de « blocage »
Rien en plus
Détourner CTRL-C
26
Version Octobre 2012 N°337
sigaction: options
Pour handler
Version Octobre 2012 N°338
sigaction: handler
Si SA_SIGINFO
theadinfo non étudié
27
Version Octobre 2012 N°339
Signaux: envoi / réaction
…
1 2 31
Handler1(){…} Handler2(){…} main(){
… sigaction …
}
PID: 1003
0 1 …
1 2 31
Réception du signal
Spécif. comportement
main(){… kill (1003, 1); kill (1003, 2);
kill (1003, 3); kill (1003, 31); …}
PID: 1055
dans 1055 ?
…
1 2 31 Masquage du signal
Consultation / modification sigprocmask
Version Octobre 2012 N°341
Modification / consultation du masque des signaux set: signaux sur lesquels appliquer how BLOCK : nouveaux signaux à masquer SETMASK : signaux à masquer UNBLOCK : signaux à démasquer
sigprocmask : gestion du masque
Masque courant ou ancien masque
SIG… BLOCK UNBLOCK SETMASK
set = NULL : consultation
28
Version Octobre 2012 N°342
sigprocmask : exemple
…
int main () {
sigset_t ancien, nouveau;
sigemptyset (&nouveau) // initialisation indispensable
sigfillset(&nouveau)
sigprocmask (SIG_SETMASK, &nouveau, &ancien);
/* …. Section critique … */
sigprocmask (SIG_SETMASK, &ancien, &nouveau);
}
Version Octobre 2012 N°343
sigpending : signaux bloqués
résultat
Signaux émis et bloqués pour le processus
29
Version Octobre 2012 N°344
sigpending : exemple
…
int main () { sigset_t ancien, nouveau, s; sigemptyset (&nouveau);
sigfillset(&nouveau)
sigprocmask (SIG_SETMASK, &nouveau, &ancien);
kill(getpid(), SIGHUP);
sleep (5);
if (sigpending (&s) == 0)
if (sigismember (&s, SIGHUP))
printf(« SIGHUP est bloqué »);
sigprocmask (SIG_SETMASK, &ancien, &nouveau);
}
Version Octobre 2012 N°345
Exemple d’utilisation (1)
Masquer le signal associé
signal associé en attente
signal associé démasqué
30
Version Octobre 2012 N°346
Exemple d’utilisation (2)
Association une seule fois
Attention si un printf est interrompu par l’arrivée
du signal
Version Octobre 2012 N°347
sigsuspend : Mise en attente fiable
Signaux à masquer
Mise en attente + masquage de set
si signal non masqué émis : traitement attendu retour après sigsuspend + restauration du masque avant
sigsuspend (si handler associé au signal émis) sinon: ignore les signal émis ou action par défaut
31
Version Octobre 2012 N°348
sigsuspend : exemple
…
int main () {
sigset_t masque;
sigemptyset (&masque);
sigaddset(&masque, SIGTERM)
sigsuspend (&masque);
}
Le signal SIGTERM est bloqué
jusqu'à l'arrivé d'un signal non bloqué.
Version Octobre 2012 N°349
Envoi de signal: compléments
Autre fonction C: killpg (p, sig) = kill (-p, sig)
Autres commandes : killall, slay
commandes de nom X,
de l'utilisateur X
Autre information importante :
Table des processus: positionnement indicateur
Pas d'effet immédiat
Appels kill/signal: Ne pas préjuger de
l'ordonnancement !!
32
Version Octobre 2012 N°350
Mise en attente non fiable
Section critique protégée de
SIGINT
Version Octobre 2012 N°351
Mise en attente fiable
Section critique protégée de
SIGINT
Débloc. SIGINT + attente
Continuation: signal
reçu
Permet de continuer en séquence
Restauration masque initial
33
Version Octobre 2012 N°352
Implantation fiable de sleep (1)
Activation de la réaction de ALRM
Comportement proche de signal
Pas de blocage de signaux y
compris ALRM
oldact = masque avant
capture de ALRM
sleep(n) fait « attendre » le processus n secondes sauf si un signal est reçu par le processus
Rien de plus
Version Octobre 2012 N°353
Implantation fiable de sleep (2)
Sauvegarde masque + Blocage de SIGALRM
SIGALRM ou un autre signal débloquera l’attente
Déblocage de SIGALRM +
pause
Le blocage est fait « à l’extérieur » de sigaction pour pouvoir y inclure SIGALRM seulement pendant alarm
34
Version Octobre 2012 N°354
Implantation fiable de sleep (3)
un signal est intervenu et
«a débloqué» sigsuspend
Restauration de la réaction
Restauration du masque
Simplement débloquer si ALRM envoyé