10.03.2014 Views

TP 10 (prog. système) Signaux - IUT d'Arles

TP 10 (prog. système) Signaux - IUT d'Arles

TP 10 (prog. système) Signaux - IUT d'Arles

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

Iut Arles / A1SE<br />

Systèmes d’exploitation<br />

<strong>TP</strong> <strong>10</strong> (<strong>prog</strong>. système) <strong>Signaux</strong><br />

Il existe sous Linux 64 signaux différents qui permettent de faire passer un message et<br />

éventuellement (cf 2ème exemple) des informations. Les 32 premiers signaux sont réservés au<br />

systèmes (SIGCHLD, SIGHINT, SIGSEGV, SIGPWR, ...) et permettent la communication entre<br />

processus. La liste des signaux est disponible par la commande « kill -l » :<br />

1) SIGHUP<br />

2) SIGINT<br />

3) SIGQUIT<br />

4) SIGILL<br />

5) SIGTRAP<br />

6) SIGABRT<br />

7) SIGBUS<br />

8) SIGFPE<br />

9) SIGKILL<br />

<strong>10</strong>) SIGUSR1<br />

11) SIGSEGV<br />

12) SIGUSR2<br />

13) SIGPIPE<br />

14) SIGALRM<br />

15) SIGTERM<br />

16) SIGSTKFLT<br />

17) SIGCHLD<br />

18) SIGCONT<br />

19) SIGSTOP<br />

20) SIGTS<strong>TP</strong><br />

21) SIGTTIN<br />

22) SIGTTOU<br />

23) SIGURG<br />

24) SIGXCPU<br />

25) SIGXFSZ<br />

26) SIGVTALRM<br />

27) SIGPROF<br />

28) SIGWINCH<br />

29) SIGIO<br />

30) SIGPWR<br />

31) SIGSYS<br />

34) SIGRTMIN<br />

35) SIGRTMIN+1<br />

36) SIGRTMIN+2<br />

37) SIGRTMIN+3<br />

38) SIGRTMIN+4<br />

39) SIGRTMIN+5<br />

40) SIGRTMIN+6<br />

41) SIGRTMIN+7<br />

42) SIGRTMIN+8<br />

43) SIGRTMIN+9<br />

44) SIGRTMIN+<strong>10</strong><br />

45) SIGRTMIN+11<br />

46) SIGRTMIN+12<br />

47) SIGRTMIN+13<br />

48) SIGRTMIN+14<br />

49) SIGRTMIN+15<br />

50) SIGRTMAX-14<br />

51) SIGRTMAX-13<br />

52) SIGRTMAX-12<br />

53) SIGRTMAX-11<br />

54) SIGRTMAX-<strong>10</strong><br />

55) SIGRTMAX-9<br />

56) SIGRTMAX-8<br />

57) SIGRTMAX-7<br />

58) SIGRTMAX-6<br />

59) SIGRTMAX-5<br />

60) SIGRTMAX-4<br />

61) SIGRTMAX-3<br />

62) SIGRTMAX-2<br />

63) SIGRTMAX-1<br />

64) SIGRTMAX<br />

Par exemple pour tuer un processus, la commande « kill – 9 3271 » envoie en fait le signal<br />

« SIGKILL » au processus numéro 3271. Le signal « SIGINT » est une interruption par<br />

l'utilisateur (par exemple lors de l'appui de « CTRL-C » dans une commande). Pour avoir la<br />

liste descriptive de chaque signal, consultez le manuel de la fonction « signal » (section 7 du<br />

man : « man 7 signal »).<br />

1. 1er exercice : test simple sur CTRL-C<br />

Le traitement des signaux se fait en déclarant au début du « main() » les signaux<br />

traités par la primitive « signal(...) ». Le code de cet exemple est dans<br />

« test_signal_simple.cpp » des sources du <strong>TP</strong>. Le principe est d'attendre un signal (la<br />

fonction « pause() » endort le processus jusqu'à la réception d'un signal) et si on reçoit<br />

« SIGINT » (signal d'interruption), on sorte du <strong>prog</strong>ramme par un « exit() ».<br />

Évidemment cette façon de faire n'est pas très belle puisqu'on n'aura pas le temps de<br />

fermer les fichiers, rendre les ressources du <strong>prog</strong>ramme (fuites de mémoires et tutti<br />

quanti) :<br />

//fonction de traitement des signaux<br />

void traitement_signaux(const int num_signal) {<br />

switch (num_signal) {<br />

//Qu'est-ce qu'on fait si on reçoit un signal d'appui sur CTRL-C ?<br />

case SIGINT : std::cerr


Iut Arles / A1SE<br />

Systèmes d’exploitation<br />

}<br />

note : la fonction « atexit » dans le fichier source peut vous aider pour désaloouer les<br />

ressources avant de sortir du <strong>prog</strong>ramme.<br />

2. Exercice 2 : mise en place d'une alarme<br />

Nous allons maintenant étudier la gestion d'une alarme par récupération du signal<br />

correspondant. On peut positionner une alarme par la fonction « alarm(secondes) ». Le code<br />

source d'exemple est « test_signal_alarme.cpp ». Il complète le précèdent en ajoutant une<br />

attente d'un événement d'alarme sur un timer réglé à 5 secondes. Si l'utilisateur ne s'est pas<br />

manifesté, le <strong>prog</strong>ramme se termine.<br />

3. Exercice 3 : signaux temps réels<br />

Les 32 autres signaux Linux sont disponible pour l'utilisateur. La valeur minimale de leur rang<br />

est donnée par SIGRTMIN (valeur prédéfinie du système, normalement 34). Un processus gère<br />

une file de signaux reçus (max. <strong>10</strong>24) dans laquelle il prend au fur et à mesure. Les<br />

occurrences sont automatiquement éliminées. On peut attacher au signal quelques<br />

informations, comme le montre l'exemple ci-dessus (entier ou pointeur sur un tableau<br />

d'entiers).<br />

Les prérequis sont : d'avoir 2 processus au moins, de déclarer (pour le receveur) une structure<br />

qui contient les signaux qu'il bloque (sigemptyset, sigaddset), une structure pour récupérer les<br />

informations (struct siginfo infos_recues), un masquage des signaux courants pour filtrer ceux<br />

qui l'intéresse (sigprocmask) et d'attendre (sigwaitinfo, bloquant). Pour l'émetteur, il suffit<br />

d'empaqueter les informations dans une structure et de les placer dans la file des messages du<br />

receveur (sigqueue).<br />

Exemple de code pour envoyer des signaux temps réels d'un processus à un autre (cf .<br />

« test_signal_tempsreel_perefils.cpp ») :<br />

● le père utilise « sigqueue() » pour envoyer un message :<br />

int execution_pere(const unsigned int _pid_fils) {<br />

//une structure pour contenir des informations à envoyer par le message<br />

union sigval infos_envoyees;<br />

//on stocke dans la structure infos_envoyees la valeur <strong>10</strong><br />

infos_envoyees.sival_int = <strong>10</strong>;<br />

std::cout


Iut Arles / A1SE<br />

Systèmes d’exploitation<br />

4. Exercice 4 : et pour finir<br />

Utiliser les signaux temps-réels pour faire passer un pointeur sur un tableau d'entiers<br />

d'une processus à un autre. Pour vous aider, allez faire un tour du côté de la structure<br />

« union sigval », il y a un champ « .sival_ptr ». Il faut déjà déclarer et remplir ce<br />

tableau dans le « main() » car vous n'avez pas encore vu la mémoire partagée.<br />

Attention cette dernière question prend un peu de temps, faites-la plutôt chez vous en<br />

entraînement.<br />

R Raffin, W. Famy & A. François p. 3/3

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!