C++ Gestion des signaux

Les signaux sont des interruptions délivrées à un processus par le système d'exploitation, qui peuvent terminer prématurément un programme. Sur les systèmes UNIX, LINUX, Mac OS X ou Windows, une interruption peut être générée en appuyant sur Ctrl+C.

Certains signaux ne peuvent pas être interceptés par un programme, mais les signaux listés dans le tableau suivant peuvent être interceptés dans un programme, et des actions appropriées peuvent être prises en fonction du signal. Ces signaux sont définis dans le fichier d'en-tête C++ <csignal>.

signal Description
SIGABRT Arrêt anormal d’un programme, tel qu’un appel àabort。
SIGFPE Opérations arithmétiques erronées, telles que la division par zéro ou des opérations provoquant un dépassement de capacité.
SIGILL Détecter les instructions illégales.
SIGINT Signal de terminaison (interruption) du programme.
SIGSEGV Accès mémoire illégal.
SIGTERM Une demande de terminaison envoyée au programme.

fonction signal()

La bibliothèque de gestion des signaux C++ fournit unsignal. Une fonction utilisée pour capturer des événements inattendus. Ci-dessous se trouve la syntaxe de la fonction signal() :

void (*signal (int sig, void (*func)(int)))(int); 

Cela semble un peu lourd. Le format de syntaxe suivant est plus facile à comprendre :

signal(registered signal, signal handler)

Cette fonction prend deux paramètres : le premier paramètre est l'identifiant du signal à définir, et le deuxième paramètre est un pointeur vers la fonction de gestion du signal. La valeur de retour de la fonction est un pointeur vers la fonction de gestion du signal précédente. Si aucune fonction de gestion de signal n'a été définie précédemment, la valeur de retour est SIG_DFL. Si la fonction de gestion de signal précédemment définie était SIG_IGN, la valeur de retour est SIG_IGN.

Écrivons un programme C++ simple qui utilise la fonction signal() pour intercepter le signal SIGINT. Quel que soit le signal que vous souhaitez intercepter dans un programme, vous devez utiliser la fonctionsignalpour enregistrer un signal et l'associer à un gestionnaire de signal. Considérez l'exemple suivant :

Exemple

#include <iostream> #include <csignal> #include <unistd.h> using namespace std; void signalHandler( int signum ) { cout << "Signal d'interruption (" << signum << ") reçu.\n"; // Nettoyer et fermer // Terminer le programme exit(signum); } int main () { // Enregistrer le signal SIGINT et le gestionnaire de signal signal(SIGINT, signalHandler); while(1){ cout << "Je vais dormir...." << endl; sleep(1); } return 0; }

Lorsque le code ci-dessus est compilé et exécuté, il produit les résultats suivants :

Going to sleep....
Going to sleep....
Going to sleep....

Maintenant, appuyez sur Ctrl+C pour interrompre le programme. Vous verrez le programme intercepter le signal. Le programme affiche le contenu suivant et se termine :

Going to sleep....
Going to sleep....
Going to sleep....
Interrupt signal (2) received.

fonction raise()

Vous pouvez utiliser la fonctionraise()Génère un signal. Cette fonction prend comme paramètre un numéro de signal entier. La syntaxe est la suivante :

int raise (signal sig);

Ici,sigest le numéro du signal à envoyer. Ces signaux incluent : SIGINT, SIGABRT, SIGFPE, SIGILL, SIGSEGV, SIGTERM, SIGHUP. Voici un exemple de génération d’un signal en interne à l’aide de la fonction raise() :

Exemple

#include <iostream> #include <csignal> #include <unistd.h> using namespace std; void signalHandler( int signum ) { cout << "Signal d'interruption (" << signum << ") reçu.\n"; // Nettoyer et fermer // Terminer le programme exit(signum); } int main () { int i = 0; // Enregistrer le signal SIGINT et le gestionnaire de signal signal(SIGINT, signalHandler); while(++i){ cout << "Passage en veille...." << endl; if( i == 3 ){ raise( SIGINT); } sleep(1); } return 0; }

Lorsque le code ci-dessus est compilé et exécuté, il produit les résultats suivants et se terminera automatiquement :

Going to sleep....
Going to sleep....
Going to sleep....
Interrupt signal (2) received.
autres extensions