Signal
Et signal er en begivenhed, der genereres for at underrette en proces eller tråd om, at en vigtig situation er ankommet. Når en proces eller tråd har modtaget et signal, stopper processen eller tråden, hvad den laver, og foretager sig noget. Signal kan være nyttigt til kommunikation mellem processer.
Standard signaler
Signalerne er defineret i headerfilen signal.h som en makrokonstant. Signalnavnet er startet med et “SIG” og efterfulgt af en kort beskrivelse af signalet. Så hvert signal har en unik numerisk værdi. Dit program skal altid bruge navnet på signalerne, ikke signalnummeret. Årsagen er, at signalnummeret kan variere alt efter system, men betydningen af navne vil være standard.
Makroen NSIG er det samlede antal definerede signal. Værdien af NSIG er et større end det samlede antal definerede signal (Alle signalnumre tildeles fortløbende).
Følgende er standardsignaler:
Signalnavn | Beskrivelse |
SIGHUP | Læg processen op. SIGHUP-signalet bruges til at rapportere afbrydelse af brugerens terminal, muligvis fordi en fjernforbindelse går tabt eller lægger på. |
SIGINT | Afbryd processen. Når brugeren skriver INTR-tegnet (normalt Ctrl + C) sendes SIGINT-signalet. |
SIGQUIT | Afslut processen. Når brugeren skriver QUIT-tegnet (normalt Ctrl + \), sendes SIGQUIT-signalet. |
SIGILL | Ulovlig instruktion. Når der forsøges at udføre skrald eller privilegeret instruktion, genereres SIGILL-signalet. SIGILL kan også genereres, når stakken løber over, eller når systemet har problemer med at køre en signalbehandler. |
SIGTRAP | Sporfælde. En breakpoint-instruktion og anden fældeinstruktion genererer SIGTRAP-signalet. Fejlfindingsprogrammet bruger dette signal. |
SIGABRT | Abort. SIGABRT-signalet genereres, når funktionen afbryde () kaldes. Dette signal indikerer en fejl, der registreres af selve programmet og rapporteres af funktionen afbryd () -opkald. |
SIGFPE | Flydende undtagelse. Når der opstod en fatal aritmetisk fejl, genereres SIGFPE-signalet. |
SIGUSR1 og SIGUSR2 | Signalerne SIGUSR1 og SIGUSR2 kan bruges som du ønsker. Det er nyttigt at skrive en signalbehandler til dem i programmet, der modtager signalet til enkel inter-proces kommunikation. |
Standardhandling af signaler
Hvert signal har en standardhandling, en af følgende:
Semester: Processen afsluttes.
Kerne: Processen afsluttes og producerer en kerne-dumpfil.
Tænd: Processen ignorerer signalet.
Hold op: Processen stopper.
Fortsat: Processen vil fortsat blive stoppet.
Standardhandling kan ændres ved hjælp af handlerfunktion. Nogle signalets standardhandling kan ikke ændres. SIGKILL og SIGABRT signalets standardhandling kan ikke ændres eller ignoreres.
Signalhåndtering
Hvis en proces modtager et signal, har processen et valg af handling for den slags signal. Processen kan ignorere signalet, kan specificere en behandlingsfunktion eller acceptere standardhandlingen for den slags signal.
- Hvis den angivne handling for signalet ignoreres, kasseres signalet med det samme.
- Programmet kan registrere en handlerfunktion ved hjælp af en funktion som f.eks signal eller sigaction. Dette kaldes en handler, der fanger signalet.
- Hvis signalet hverken er blevet håndteret eller ignoreret, finder dets standardhandling sted.
Vi kan håndtere signalet ved hjælp af signal eller sigaction fungere. Her ser vi, hvordan det enkleste signal() funktion bruges til håndtering af signaler.
int signal () (int signum, void (* func) (int))Det signal() vil kalde func funktion, hvis processen modtager et signal signum. Det signal() returnerer en markør, der skal fungere func hvis det lykkes, eller hvis det returnerer en fejl til errno og -1 ellers.
Det func markøren kan have tre værdier:
- SIG_DFL: Det er en markør til systemets standardfunktion SIG_DFL (), erklæret i h header-fil. Det bruges til at udføre standardhandling af signalet.
- SIG_IGN: Det er en pointer til system ignorere funktion SIG_IGN (),erklæret i h header-fil.
- Brugerdefineret handlerfunktionsmarkør: Den brugerdefinerede handlerfunktionstype er ugyldig (*) (int), betyder returtype er ugyldig, og et argument af typen int.
Grundlæggende signalhåndteringseksempel
#omfatte#omfatte
#omfatte
ugyldig sig_handler (int signum)
// Returtypen for handlerfunktionen skal være ugyldig
printf ("\ nIndvendig handlerfunktion \ n");
int main ()
signal (SIGINT, sig_handler); // Registrer signalhåndterer
for (int i = 1 ;; i ++) // Infinite loop
printf ("% d: Inde i hovedfunktionen \ n", i);
søvn (1); // Forsink i 1 sekund
returnere 0;
På skærmbilledet af output fra eksempel 1.c, kan vi se, at i hovedfunktion udføres uendelig løkke. Når brugeren skrev Ctrl + C, stoppes udførelsen af hovedfunktionen og signalets behandlerfunktion. Efter afslutningen af behandlerfunktionen genoptog udførelsen af hovedfunktionen. Når brugertypen er skrevet Ctrl + \, afsluttes processen.
Ignorer eksempler på signaler
#omfatte#omfatte
#omfatte
int main ()
signal (SIGINT, SIG_IGN); // Registrer signalhåndterer for at ignorere signalet
for (int i = 1 ;; i ++) // Infinite loop
printf ("% d: Inde i hovedfunktionen \ n", i);
søvn (1); // Forsink i 1 sekund
returnere 0;
Her registreres handlerfunktionen til SIG_IGN () funktion til ignorering af signalhandling. Så når brugeren skrev Ctrl + C, SIGINT signalet genereres, men handlingen ignoreres.
Omregistrer signalhåndteringseksempel
#omfatte#omfatte
#omfatte
ugyldig sig_handler (int signum)
printf ("\ nIndvendig handlerfunktion \ n");
signal (SIGINT, SIG_DFL); // Registrer signalhåndterer igen for standardhandling
int main ()
signal (SIGINT, sig_handler); // Registrer signalhåndterer
for (int i = 1 ;; i ++) // Infinite loop
printf ("% d: Inde i hovedfunktionen \ n", i);
søvn (1); // Forsink i 1 sekund
returnere 0;
På skærmbilledet af output fra eksempel 3.c, kan vi se, at når brugeren første gang skrev Ctrl + C, påkaldte handlerfunktionen. I behandlerfunktionen registreres signalbehandleren igen til SIG_DFL for signalets standardhandling. Når brugeren skrev Ctrl + C for anden gang, afsluttes processen, hvilket er standardhandlingen for SIGINT signal.
Afsendelse af signaler:
En proces kan også eksplicit sende signaler til sig selv eller til en anden proces. hæve () og dræbe () funktion kan bruges til at sende signaler. Begge funktioner erklæres i signal.h header-fil.
int hæve (int signum)Funktionen hæve () bruges til at sende signal signum til opkaldsprocessen (sig selv). Det returnerer nul, hvis det lykkes, og en ikke-nul værdi, hvis det mislykkes.
int kill (pid_t pid, int signum)Drabfunktionen, der bruges til at sende et signal signum til en proces eller procesgruppe, der er specificeret af pid.
SIGUSR1 Signalhåndteringseksempel
#omfatte#omfatte
ugyldig sig_handler (int signum)
printf ("Inside handler-funktion \ n");
int main ()
signal (SIGUSR1, sig_handler); // Registrer signalhåndterer
printf ("Inde hovedfunktion \ n");
hæve (SIGUSR1);
printf ("Inde hovedfunktion \ n");
returnere 0;
Her sender processen SIGUSR1-signalet til sig selv ved hjælp af funktionen raise ().
Hæv med Kill Example Program
#omfatte#omfatte
#omfatte
ugyldig sig_handler (int signum)
printf ("Indehåndteringsfunktion \ n");
int main ()
pid_t pid;
signal (SIGUSR1, sig_handler); // Registrer signalhåndterer
printf ("Inde hovedfunktion \ n");
pid = getpid (); // Process-ID for sig selv
dræbe (pid, SIGUSR1); // Send SIGUSR1 til sig selv
printf ("Inde hovedfunktion \ n");
returnere 0;
Her sendes processen SIGUSR1 signal til sig selv ved hjælp af dræbe() fungere. getpid () bruges til at få proces-ID'et af sig selv.
I det næste eksempel vil vi se, hvordan forældre- og barnprocesser kommunikerer (Inter Process Communication) ved hjælp af dræbe() og signalfunktion.
Forældrebørns kommunikation med signaler
#omfatte#omfatte
#omfatte
#omfatte
ugyldigt sig_handler_parent (int signum)
printf ("Forælder: Modtaget et svarsignal fra barnet \ n");
ugyldigt sig_handler_child (int signum)
printf ("Barn: Modtaget et signal fra forælder \ n");
søvn (1);
dræb (getppid (), SIGUSR1);
int main ()
pid_t pid;
hvis ((pid = gaffel ())<0)
printf ("Gaffel mislykkedes \ n");
udgang (1);
/ * Barneproces * /
ellers hvis (pid == 0)
signal (SIGUSR1, sig_handler_child); // Registrer signalhåndterer
printf ("Barn: venter på signal \ n");
pause();
/ * Forældreproces * /
andet
signal (SIGUSR1, sig_handler_parent); // Registrer signalhåndterer
søvn (1);
printf ("Forælder: sender signal til barn \ n");
dræbe (pid, SIGUSR1);
printf ("Forælder: venter på svar \ n");
pause();
returnere 0;
Her, gaffel() funktion skaber underordnet proces og returnerer nul til underordnet proces og underordnet proces-id til forældreproces. Så pid er blevet kontrolleret for at bestemme forældre- og barneproces. I forældreprocessen soves den i 1 sekund, så underordnet proces kan registrere signalhåndteringsfunktion og vente på signalet fra forælder. Efter 1 sekund forældre proces sende SIGUSR1 signal til barn-processen, og vent på svarets signal fra barnet. I underordnet proces venter det først på signal fra forælder, og når signal modtages, kaldes handlerfunktion. Fra behandlerfunktionen sender barneprocessen en anden SIGUSR1 signal til forælder. Her getppid () funktion bruges til at hente forældreproces-id.
Konklusion
Signal i Linux er et stort emne. I denne artikel har vi set, hvordan man håndterer signal fra det helt grundlæggende, og også får en viden om, hvordan signalet genererer, hvordan en proces kan sende signal til sig selv og anden proces, hvordan signal kan bruges til kommunikation mellem processer.