Programmation C source/gestion des signaux

Un livre de Wikilivres.
Programmation C source
Programmation C++
Programmation C++
Sommaire
Modifier ce modèle
#include <stdio.h>
#include <signal.h>

int main(void)
{
	printf("----------------------------------------\n");
	printf(" Gestion des signaux\n");
	printf("----------------------------------------\n");

	/*
	   Les signaux permettent une communication, assez sommaire, entre le système et un
	   processus, ou entre différents processus. Un signal ne porte qu'une seule
	   information: son numéro, de type int. Un processus peut s'envoyer un signal à
	   lui-même. Ces signaux sont envoyés de manière asynchrone: lorsqu'un processus
	   reçoit un signal, son exécution est interrompue, et une fonction spécifique, dite
	   gestionnaire de signal, est appelée, avec en paramètre le numéro du signal reçu,
	   pour traiter l'événement. Lorsque cette fonction se termine, le processus reprend
	   là où il s'était arrêté. C'est à chaque processus de déterminer ce qu'il fait
	   quand il reçoit un signal de numéro donné, en définissant un gestionnaire de
	   signal pour tous les signaux qu'il le souhaite. En l'absence de précisions dans
	   nos programmes, l'implémentation fournira en effet un gestionnaire de signal par
	   défaut, qui le plus souvent se contentera d'arrêter le programme.
	*/

	#if 0
	 #include <signal.h>
	 signal()	// pour définir un gestionnaire de signal
	 raise()	// pour envoyer un signal au processus courant
	#endif

	/*
	   Le C définit ces deux fonctions, et pas plus.
	   On retrouve donc signal() et raise() sur tous les sytèmes d'exploitation
	   qui propose le langage C; mais pour d'autres fonctions, elles sont propres
	   à tel ou tel système. Par exemple nous avons les fonctions de gestion de
	   signaux, définies par la norme POSIX, pour les systèmes qui ont choisi de
	   respecter la norme POSIX.
	*/

	#if 0
	 void (*   signal( int sig, void (*func)(int) )   )(int);

	 typedef void (*handler_t)(int);
	 handler_t signal(int sig, handler_t func);
	#endif

	/*
	   les paramètres :
		sig	numéro de signal
		func	pointeur vers la fonction de gestion du signal

	   pour sig : dans signal.h
		nous avons un certain nombre de signaux définit par des macros
		par exemple SIGSEGV qui indique un accès illégal à la mémoire (SEGmentation
		Violation)

	   pour func : dans signal.h, nous avons
		SIG_IGN		le signal sera ignoré
		SIG_DFL		le gestionnaire de signal par défaut sera mis en place
		sinon bien sur il faut donner une fonction que nous avons écrite !

	   retour de signal() :

	   En cas d'erreur, la fonction renvoie SIG_ERR et place la variable errno à une
	   valeur significative.

	   Exemple :
	   avec le signal SIGFPE, qui normalement est là pour indiquer une exception
	   lors des calculs en virgule flottante (Floating Point Exception)
	*/

	void sig_fpe(int sig)
	{
		// grace au paramètre sig, cette fonction pourrait traiter différents signaux
		if (sig == SIGFPE)
			puts("le signal SIGFPE a été reçu, execution de sig_fpe()");
		else
			puts("sig_fpe() : signal reçu inconnu !");
	}

	if (signal(SIGFPE, sig_fpe) == SIG_ERR)
	{
		puts("Le gestionnaire de signal pour SIGFPE n'a pu etre defini.");
	}
	else
	{
		puts("Le gestionnaire de signal pour SIGFPE a pu etre defini.");
	}

	raise(SIGFPE);

	while(1);

	return 0;
}