Cours:TdProgSyst
Sommaire
Td 12 Eléments de programmation système
Gestion des signaux
Deux fonctions du langage C permettent de travailler avec les signaux d’UNIX: la fonction **kill** et **signal**. La première permet d’envoyer un signal à un processus dont on connait le numéro de processus (le PID), et
la fonction signal permet d’associer une fonction écrite par
l’utilisateur à un signal UNIX: lorsque ce dernier est reçu, la fonction est
exécutée.
Les signaux les plus classiques sont les suivants:
SIGINT signal envoyé par UNIX lors d’un Ctrl C pour stopper le processus SIGHUP signal émis par UNIX lors de la déconnexion SIGALRM signal émis par la fonction alarm() SIGUSR1 signal à la disposition de l’utilisateur SIGUSR2 autre signal à la disposition de l’utilisateur
Un exemple d’utilisation de ces fonctions est représenté ci-dessous:
#include <stdio.h> #include <sys/types.h> #include <signal.h>
void gestion_signal() {
... // code de gestion du signal
}
main() {
...
signal(SIGUSR1,gestion_signal); // qd on reçoit SIGUSR1, exécute gestion_signal()
...
}
Chaque fois que le processus recevra le signal SIGUSR1, on ira exécuter la fonction gestion_signal. Pour ceux qui connaissent le concept d’ interruption, il s’agit ici d’une interruption logicielle.
La fonction alarm permet à un processus de s’auto-envoyer le signal SIGALRM au bout d’une certaine temporisation exprimée en secondes.
Exercices
1. Ecrire un programme ignorant les arrêts claviers (CTRL+C, ...).
2. Ecrire un programme ignorant le signal émis lors de la déconnexion.
3. Ecrire un programme affichant toutes les dix secondes la chaîne de caractères coucou sur l’écran.
4. (Hors TD) Ecrire un programme permettant d’afficher le numéro des signaux reçus par le programme.
Duplication de processus
La fonction fork permet à un processus de se dupliquer en mémoire: le segment de code, le segment de données et la pile sont dupliqués. Après l’appel de fork, deux processus identiques s’exécutent alors en mémoire. La valeur de retour de fork permet de savoir dans quel processus on se trouve. Si fork retourne:
- la valeur 0, on est dans le fils.
- une valeur positive, on est dans le père. La valeur retournée est le PID du fils.
- la valeur -1, fork n’a pu s’exécuter pour des raisons diverses: par exemple, plus de mémoire disponible...
Un exemple d'utilisation est:
#include<sys/types.h> #include<unistd.h>
main() {
int pid;
...
switch (pid=fork()) {
case 0: // -------------------- on est dans le fils
.... // code du fils
exit(0); // fin du fils
case -1: // -------------------- erreur du fork
perror("erreur dans fork");
exit(-1);
default: // -------------------- on est dans le père
... // code du père
}
...
}