C Programmering

Hvordan bruke signalbehandlere på C-språk?

Hvordan bruke signalbehandlere på C-språk?
I denne artikkelen skal vi vise deg hvordan du bruker signalbehandlere i Linux ved hjelp av C-språk. Men først vil vi diskutere hva som er signal, hvordan det vil generere noen vanlige signaler som du kan bruke i programmet ditt, og så vil vi se hvordan forskjellige signaler kan håndteres av et program mens programmet kjøres. Så la oss begynne.

Signal

Et signal er en hendelse som genereres for å varsle en prosess eller tråd om at en viktig situasjon er kommet. Når en prosess eller tråd har mottatt et signal, vil prosessen eller tråden stoppe hva den gjør og iverksette tiltak. Signal kan være nyttig for kommunikasjon mellom prosesser.

Standard signaler

Signalene er definert i toppfilen signal.h som en makrokonstant. Signalnavnet har startet med et “SIG” og etterfulgt av en kort beskrivelse av signalet. Så, hvert signal har en unik numerisk verdi. Programmet ditt bør alltid bruke navnet på signalene, ikke signalnummeret. Årsaken er at signalnummeret kan variere i henhold til systemet, men betydningen av navnene vil være standard.

Makroen NSIG er det totale antallet signal som er definert. Verdien av NSIG er et større enn det totale antallet definerte signaler (Alle signalnumre tildeles fortløpende).

Følgende er standardsignalene:

Signalnavn Beskrivelse
SIGHUP Legg på prosessen. SIGHUP-signalet brukes til å rapportere frakobling av brukerens terminal, muligens fordi en ekstern tilkobling går tapt eller legger på.
SIGINT Avbryt prosessen. Når brukeren skriver INTR-tegnet (normalt Ctrl + C), sendes SIGINT-signalet.
SIGQUIT Avslutt prosessen. Når brukeren skriver QUIT-tegnet (normalt Ctrl + \), sendes SIGQUIT-signalet.
SIGILL Ulovlig instruksjon. Når det blir gjort et forsøk på å utføre søppel eller privilegert instruksjon, genereres SIGILL-signalet. SIGILL kan også genereres når stabelen renner over, eller når systemet har problemer med å kjøre en signalbehandler.
SIGTRAP Sporfelle. En bruddpunktinstruksjon og annen felleinstruksjon vil generere SIGTRAP-signalet. Feilsøkingsprogrammet bruker dette signalet.
SIGABRT Avbryte. SIGABRT-signalet genereres når abort () -funksjonen kalles. Dette signalet indikerer en feil som oppdages av selve programmet og rapporteres av funksjonen samtalen avbryte ().
SIGFPE Flytende punkt unntak. Når det oppstod en dødelig aritmetisk feil, genereres SIGFPE-signalet.
SIGUSR1 og SIGUSR2 Signalene SIGUSR1 og SIGUSR2 kan brukes som du ønsker. Det er nyttig å skrive en signalbehandler for dem i programmet som mottar signalet for enkel kommunikasjon mellom prosesser.

Standard handling av signaler

Hvert signal har en standardhandling, ett av følgende:

Begrep: Prosessen avsluttes.
Kjerne: Prosessen avsluttes og produseres en kjernedumpfil.
Ign: Prosessen vil ignorere signalet.
Stoppe: Prosessen vil stoppe.
Fortsett: Prosessen vil fortsette fra å bli stoppet.

Standardhandling kan endres ved hjelp av behandlerfunksjonen. Noen signalets standardhandling kan ikke endres. SIGKILL og SIGABRT signalets standardhandling kan ikke endres eller ignoreres.

Signalhåndtering

Hvis en prosess mottar et signal, har prosessen et valg av handling for den typen signal. Prosessen kan ignorere signalet, spesifisere en behandlerfunksjon eller godta standardhandlingen for den typen signal.

Vi kan håndtere signalet ved hjelp av signal eller sigaksjon funksjon. Her ser vi hvordan det enkleste signal() funksjonen brukes til å håndtere signaler.

int signal () (int signum, void (* func) (int))

De signal() vil kalle func funksjon hvis prosessen mottar et signal signum. De signal() returnerer en peker for å fungere func hvis vellykket eller det returnerer en feil til errno og -1 ellers.

De func pekeren kan ha tre verdier:

  1. SIG_DFL: Det er en peker til systemets standardfunksjon SIG_DFL (), erklært i h topptekstfil. Den brukes til å utføre standardhandling av signalet.
  2. SIG_IGN: Det er en peker til system ignorere funksjon SIG_IGN (),erklært i h topptekstfil.
  3. Brukerdefinert peker for behandlerfunksjon: Den brukerdefinerte handlerfunksjonstypen er ugyldig (*) (int), betyr returtype er ugyldig og ett argument av typen int.

Grunnleggende signalhåndteringseksempel

#inkludere
#inkludere
#inkludere
ugyldig sig_handler (int signum)
// Returtype for behandlerfunksjonen skal være ugyldig
printf ("\ nInnvendig behandlerfunksjon \ n");

int main ()
signal (SIGINT, sig_handler); // Registrer signalbehandler
for (int i = 1 ;; i ++) // Infinite loop
printf ("% d: Inne i hovedfunksjonen \ n", i);
søvn (1); // Forsink i 1 sekund

retur 0;

På skjermbildet av utgangen fra eksempel 1.c, kan vi se at i hovedfunksjon utføres uendelig sløyfe. Når brukeren skrev Ctrl + C, stoppes utførelsen av hovedfunksjonen og signalbehandlerfunksjonen. Etter at håndteringsfunksjonen var fullført, ble kjennelsen av hovedfunksjonen gjenopptatt. Når brukertypen skrev Ctrl + \, avsluttes prosessen.

Ignorer signaleksempler

#inkludere
#inkludere
#inkludere
int main ()
signal (SIGINT, SIG_IGN); // Registrer signalbehandler for å ignorere signalet
for (int i = 1 ;; i ++) // Infinite loop
printf ("% d: Inne i hovedfunksjonen \ n", i);
søvn (1); // Forsink i 1 sekund

retur 0;

Her registreres handlerfunksjonen SIG_IGN () funksjon for å ignorere signalhandlingen. Så når brukeren skrev Ctrl + C,  SIGINT signalet genereres, men handlingen ignoreres.

Omregistrer signalhåndteringseksempel

#inkludere
#inkludere
#inkludere
ugyldig sig_handler (int signum)
printf ("\ nInnvendig behandlerfunksjon \ n");
signal (SIGINT, SIG_DFL); // Registrer signalbehandleren på nytt for standardhandling

int main ()
signal (SIGINT, sig_handler); // Registrer signalbehandler
for (int i = 1 ;; i ++) // Infinite loop
printf ("% d: Inne i hovedfunksjonen \ n", i);
søvn (1); // Forsink i 1 sekund

retur 0;

På skjermbildet av utgangen fra Eksempel 3.c, kan vi se at når brukeren første gang skrev Ctrl + C, påkalte behandlerfunksjonen. I behandlerfunksjonen registreres signalbehandleren på nytt SIG_DFL for standard handling av signalet. Når brukeren skrev Ctrl + C for andre gang, avsluttes prosessen, som er standardhandling SIGINT signal.

Sende signaler:

En prosess kan også eksplisitt sende signaler til seg selv eller til en annen prosess. heve () og drepe () -funksjonen kan brukes til å sende signaler. Begge funksjonene blir signalisert.h topptekstfil.

int raise (int signum)

Hevingsfunksjonen () som brukes til å sende signal signum til kalleprosessen (seg selv). Den returnerer null hvis vellykket og en verdi som ikke er null hvis den mislykkes.

int kill (pid_t pid, int signum)

Kill-funksjonen som brukes til å sende et signal signum til en prosess eller prosessgruppe spesifisert av pid.

SIGUSR1 Signalhåndteringseksempel

#inkludere
#inkludere
ugyldig sig_handler (int signum)
printf ("Inside handler function \ n");

int main ()
signal (SIGUSR1, sig_handler); // Registrer signalbehandler
printf ("Inne i hovedfunksjonen \ n");
heve (SIGUSR1);
printf ("Inne i hovedfunksjonen \ n");
retur 0;

Her sender prosessen SIGUSR1-signal til seg selv ved hjelp av heve () -funksjonen.

Raise with Kill Example Program

#inkludere
#inkludere
#inkludere
ugyldig sig_handler (int signum)
printf ("Inside handler function \ n");

int main ()
pid_t pid;
signal (SIGUSR1, sig_handler); // Registrer signalbehandler
printf ("Inne i hovedfunksjonen \ n");
pid = getpid (); // Behandle ID for seg selv
drepe (pid, SIGUSR1); // Send SIGUSR1 til seg selv
printf ("Inne i hovedfunksjonen \ n");
retur 0;

Her sender prosessen SIGUSR1 signal til seg selv ved hjelp av drepe() funksjon. getpid () brukes til å få prosess-ID av seg selv.

I neste eksempel vil vi se hvordan foreldre- og barneprosesser kommuniserer (Inter Process Communication) ved hjelp av drepe() og signalfunksjon.

Foreldrebarns kommunikasjon med signaler

#inkludere
#inkludere
#inkludere
#inkludere
ugyldig sig_handler_parent (int signum)
printf ("Forelder: Mottatt et svarsignal fra barnet \ n");

ugyldig sig_handler_child (int signum)
printf ("Barn: Mottatt et signal fra foreldre \ n");
søvn (1);
drep (getppid (), SIGUSR1);

int main ()
pid_t pid;
hvis ((pid = gaffel ())<0)
printf ("Gaffelen mislyktes \ n");
utgang (1);

/ * Barneprosess * /
annet hvis (pid == 0)
signal (SIGUSR1, sig_handler_child); // Registrer signalbehandler
printf ("Barn: venter på signal \ n");
pause();

/ * Foreldreprosess * /
ellers
signal (SIGUSR1, sig_handler_parent); // Registrer signalbehandler
søvn (1);
printf ("Forelder: sender signal til barn \ n");
drepe (pid, SIGUSR1);
printf ("Forelder: venter på svar \ n");
pause();

retur 0;

Her, gaffel() funksjon skaper barneprosess og returnerer null til barneprosess og barneprosess-ID til foreldreprosess. Så, pid er sjekket for å avgjøre foreldre- og barneprosessen. I foreldreprosessen er den sovet i 1 sekund slik at barneprosessen kan registrere signalhåndteringsfunksjonen og vente på signalet fra foreldrene. Etter 1 sekund foreldreprosess send SIGUSR1 signal til barn prosess og vent på svar signalet fra barnet. I barneprosessen venter den først på signal fra foreldrene, og når signalet mottas, blir behandlerfunksjonen påkalt. Fra behandlerfunksjonen sender barneprosessen en annen SIGUSR1 signal til foreldre. Her getppid () funksjonen brukes til å få foreldreprosess-ID.

Konklusjon

Signal i Linux er et stort tema. I denne artikkelen har vi sett hvordan man skal håndtere signal fra det helt grunnleggende, og også få kunnskap om hvordan signalet genererer, hvordan en prosess kan sende signal til seg selv og annen prosess, hvordan signal kan brukes til kommunikasjon mellom prosesser.

Mus Mus venstreklikknapp fungerer ikke på Windows 10
Mus venstreklikknapp fungerer ikke på Windows 10
Hvis du bruker en dedikert mus med den bærbare eller stasjonære datamaskinen, men museklikk-knappen fungerer ikke på Windows 10/8/7 av en eller annen ...
Mus Markøren hopper eller beveger seg tilfeldig mens du skriver inn Windows 10
Markøren hopper eller beveger seg tilfeldig mens du skriver inn Windows 10
Hvis du finner ut at musemarkøren hopper eller beveger seg alene, automatisk, tilfeldig mens du skriver inn Windows-bærbar PC eller datamaskin, kan no...
Mus Hvordan reversere rulle retning for mus og styreplater i Windows 10
Hvordan reversere rulle retning for mus og styreplater i Windows 10
Mus og Pekeplates gjør ikke bare databehandling enkelt, men mer effektivt og mindre tidkrevende. Vi kan ikke forestille oss et liv uten disse enhetene...