next up previous
Up: No Title Previous: No Title

Subsections

Contrôle en C

Ruptures de calcul : les signaux

Les signaux en C permettent d'informer un processus qu'un événement particulier s'est produit. Chaque processus peut gérer un traitement particulier pour un signal donné. Le traitement lié à un signal associe à un signal donné une fonction de traitement. Lors du déclenchement de cet événement le programme exécute la fonction associée puis reprend l'exécution du programme là où il l'avait laissée.

Comme il y a des différences importantes entre BSD et SYSTEM V, on consultera le fichier <signal.h> pour connaître les signaux disponibles. On pose un traitement pour un signal de la manière suivante :

#include <signal.h>

signal(NUMERO_DU_SIGNAL, procedure)
La procédure est paramétrée par un entier (correspondant au numéro du signal). Il est nécessaire de réarmer le traitement d'un signal suite au traitement de celui-ci.
1.
Le signal SIGINT indique une interruption (kill -2 ou ^C) du processus. Poser un récupérateur pour le signal SIGINT qui affiche le message "Pas d'interruption possible" en cas d'arrivée de ce signal. Voici le programme principal :
main ()
{ int i;
  int c=0;
  signal(SIGINT,hand_int);
  printf("un programme qui boucle, essayer ^C pour l'arreter\n");
  while (1)
    {i++;
     if ((i % 100000) == 0) {c++;printf("."); fflush(stdout);}
    } 
}
Ecrire la procédure hand_int.
2.
Le signal SIGSEGV indique une "violation mémoire", un adressage interdit. Soit le programme suivant tiré de "la Communication sous Unix" page 163 :

small

char *p;

void hand()
{
}
main()
{
  signal(SIGSEGV,hand);
  p=(char *)sbrk(512);
  printf("valeur initiale du point de rupture : %u\n",p);
  printf("valeur du point de rupture apres sbrk : %u\n",sbrk(0));
  while(1)
      *p++='a';
}

Ecrire la fonction void hand() qui affiche la valeur de p et le point de rupture.

3.
Ecrire une fonction qui compte le nombre d'éléments d'une liste d'entiers. Ecrire ensuite un programme qui appelle cette fonction sur une grande liste et qui répond au signal SIGINT en affichant le nombre d'éléments déjà comptés.

Rupture de calcul : setjmp/longjmp

Pour certaines applications l'exécution du programme doit être reprise en un point particulier. Pour cela il est nécessaire d'utiliser des étiquettes dynamiques. On mémorise l'état de la pile d'exécution du processus dans une variable de type jmp_buf défini dans <setjmp.h> avec la fonction setjmp. Cette variable constitue l'étiquette. La fonction longjmp permet ensuite de reprendre l'exécution au point prévu en restaurant l'état de la pile. La valeur de retour de setjmp est 0 après son appel ou une valeur non nulle quand ce retour s'effectue par un longjmp (y compris dans le cas où la valeur retournée par longjmp est 0).

int setjmp(jmp_buf env);
void longjmp (jmp_buf env, int val);
1.
Ecrire une fonction récursive qui calcule le produit des éléments d'une liste d'entiers.
2.
Modifier cette fonction pour revenir directement si elle rencontre un zéro dans cette liste.

Implantation d'exceptions

Le mécanisme d'étiquettes dynamiques permet de construire un mécanisme d'exceptions (comme en ML ou ADA). On définit la syntaxe suivante pour intégrer des exceptions en C.

include "exception.h"

exception e;

Test()
{
  TRY
    Body();
  EXCEPT(e)
    Handler();
  ENDTRY
}
avec le déclenchement d'une exception par :
RAISE(e,v)
e est une exception et v un entier. TRY, EXCEPT, ENDTRY, RAISE seront des macros C, Body et Handler le programme utilisateur. Lors du déclenchement d'une exception, l'exécution du programme va au dernier récupérateur d'exceptions rencontré (TRY ... ENDTRY). Si l'exception déclenchée correspond à un des EXCEPT(e) le code de son Handler est alors exécuté, et le programme continue après le ENDTRY. Si l'exception n'est pas récupérée elle est de nouveau déclenchée pour atteindre le récupérateur précédent.

1.
Définir le type exception.
2.
Ecrire les macros TRY, EXCEPT, ENDTRY.
3.
Ecrire la fonction _RaiseException.
4.
Utiliser ce mécanisme pour le produit d'entiers d'une liste.
5.
Ecrire une fonction qui retourne les n derniers éléments d'une liste.

Utilisation des programmes décrits

On trouvera sur la machine maya.cicrp.jussieu.fr les programmes suivants :

dans le catalogue users/p6ipens/chaillou/enseignements/97-98/programmation/TD3. N'hésitez pas à les compiler (mettre l'option -traditional avec gcc pour faire passer le préprocesseur correctement), les tester, les lire et les modifier!!!

Bibliographie


next up previous
Up: No Title Previous: No Title
Emmanuel CHAILLOUX
11/6/1997