Zoeken…


Syntaxis

  • void (* signaal (int sig, void (* func) (int))) (int);

parameters

Parameter Details
sig Het signaal om de signaalhandler in te stellen op, een van SIGABRT , SIGFPE , SIGILL , SIGTERM , SIGINT , SIGSEGV of een door de implementatie gedefinieerde waarde
func De signaalhandler, die een van de volgende is: SIG_DFL , voor de standaardhandler, SIG_IGN om het signaal te negeren, of een functiepointer met de handtekening void foo(int sig); .

Opmerkingen

Het gebruik van signaalbehandelaars met alleen de garanties van de C-norm legt verschillende beperkingen op wat wel of niet kan worden gedaan in de door de gebruiker gedefinieerde signaalbehandelaar.

  • Als de door de gebruiker gedefinieerde functie terugkeert tijdens het gebruik van SIGSEGV , SIGFPE , SIGILL of een andere door de implementatie gedefinieerde hardware-interrupt, wordt het gedrag niet bepaald door de C-standaard. Dit komt omdat de interface van C geen middelen geeft om de defecte status te wijzigen (bijv. Na een deling door 0 ) en dus bij het retourneren van het programma exact dezelfde foutieve status heeft als voordat de hardware-onderbreking plaatsvond.

  • Als de door de gebruiker gedefinieerde functie werd aangeroepen als resultaat van een oproep om abort te abort of op te raise , mag de signaalhandler niet opnieuw raise .

  • Signalen kunnen midden in elke bewerking aankomen, en daarom kan de ondeelbaarheid van bewerkingen in het algemeen niet worden gegarandeerd, noch werkt signaalverwerking goed met optimalisatie. Daarom moeten alle wijzigingen in gegevens in een signaalhandler variabelen zijn

    • van het type sig_atomic_t (alle versies) of een sig_atomic_t slot (sinds C11, optioneel)
    • die volatile gekwalificeerd zijn.
  • Andere functies van de C-standaardbibliotheek zullen deze beperkingen meestal niet respecteren, omdat ze variabelen in de algemene status van het programma kunnen veranderen. De C-standaard biedt alleen garanties voor abort , _Exit (sinds C99), quick_exit (sinds C11), signal (voor hetzelfde signaalnummer) en enkele atomaire bewerkingen (sinds C11).

Gedrag wordt niet gedefinieerd door de C-norm als een van de bovenstaande regels wordt overtreden. Platforms kunnen specifieke extensies hebben, maar deze zijn over het algemeen niet draagbaar buiten dat platform.

  • Gewoonlijk hebben systemen hun eigen lijst met functies die asynchroon signaalveilig zijn , dat wil zeggen met C-bibliotheekfuncties die kunnen worden gebruikt vanuit een signaalhandler. Bijvoorbeeld, vaak is printf een van deze functies.

  • In het bijzonder definieert de C-norm niet veel over de interactie met zijn threads-interface (sinds C11) of platformspecifieke threadbibliotheken zoals POSIX-threads. Dergelijke platforms moeten zelf de interactie van dergelijke threadbibliotheken met signalen specificeren.

Signaalverwerking met "signal ()"

Signaalnummers kunnen synchroon zijn (zoals SIGSEGV - segmentatiefout) wanneer ze worden geactiveerd door een storing in het programma zelf of asynchroon (zoals SIGINT - interactieve aandacht) wanneer ze van buiten het programma worden gestart, bijvoorbeeld door een toetsdruk als Cntrl-C .

De functie signal() maakt deel uit van de ISO C-standaard en kan worden gebruikt om een functie toe te wijzen om een specifiek signaal af te handelen

#include <stdio.h>  /* printf() */
#include <stdlib.h> /* abort()  */
#include <signal.h> /* signal() */

void handler_nonportable(int sig)
{
    /* undefined behavior, maybe fine on specific platform */
    printf("Catched: %d\n", sig);
    
    /* abort is safe to call */
    abort();
}

sig_atomic_t volatile finished = 0;

void handler(int sig)
{
    switch (sig) {
    /* hardware interrupts should not return */
    case SIGSEGV:
    case SIGFPE:
    case SIGILL:
C11
      /* quick_exit is safe to call */
      quick_exit(EXIT_FAILURE);
C11
      /* use _Exit in pre-C11 */
      _Exit(EXIT_FAILURE);
    default:
       /* Reset the signal to the default handler, 
          so we will not be called again if things go
          wrong on return. */
      signal(sig, SIG_DFL);
      /* let everybody know that we are finished */
      finished = sig;
      return;
   }
}

int main(void)
{

    /* Catch the SIGSEGV signal, raised on segmentation faults (i.e NULL ptr access */
    if (signal(SIGSEGV, &handler) == SIG_ERR) {
        perror("could not establish handler for SIGSEGV");
        return EXIT_FAILURE;
    }

    /* Catch the SIGTERM signal, termination request */
    if (signal(SIGTERM, &handler) == SIG_ERR) {
        perror("could not establish handler for SIGTERM");
        return EXIT_FAILURE;
    }

    /* Ignore the SIGINT signal, by setting the handler to `SIG_IGN`. */
    signal(SIGINT, SIG_IGN);


    /* Do something that takes some time here, and leaves
       the time to terminate the program from the keyboard. */

    /* Then: */

    if (finished) {
       fprintf(stderr, "we have been terminated by signal %d\n", (int)finished);
        return EXIT_FAILURE;
    }


    /* Try to force a segmentation fault, and raise a SIGSEGV */
    {
      char* ptr = 0;
      *ptr = 0;
    }

    /* This should never be executed */
    return EXIT_SUCCESS;
}

Het gebruik van signal() legt belangrijke beperkingen op wat u binnen de signaalhandlers mag doen, zie de opmerkingen voor meer informatie.

POSIX beveelt het gebruik van sigaction() plaats van signal() , vanwege het niet-gespecificeerde gedrag en aanzienlijke implementatievariaties. POSIX definieert ook veel meer signalen dan de ISO C-standaard, inclusief SIGUSR1 en SIGUSR2 , die door de programmeur voor elk doel vrij kunnen worden gebruikt.



Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow