C Programovanie

Ako používať manipulátory signálu v jazyku C?

Ako používať manipulátory signálu v jazyku C?
V tomto článku vám ukážeme, ako používať obslužné rutiny signálu v systéme Linux pomocou jazyka C. Najskôr si ale povieme, čo je to signál, ako vygeneruje niektoré bežné signály, ktoré môžete použiť vo svojom programe, a potom sa pozrieme na to, ako môže program spracovávať rôzne signály, keď sa program vykonáva. Takže začnime.

Signál

Signál je udalosť, ktorá sa generuje s cieľom upozorniť proces alebo vlákno, že nastala dôležitá situácia. Keď proces alebo vlákno prijme signál, proces alebo vlákno zastaví svoju činnosť a urobí nejaké kroky. Signál môže byť užitočný na komunikáciu medzi procesmi.

Štandardné signály

Signály sú definované v hlavičkovom súbore signál.h ako makro konštanta. Názov signálu začínal na „SIG“ a nasledoval krátky popis signálu. Každý signál má teda jedinečnú číselnú hodnotu. Váš program by mal vždy používať názov signálov, nie číslo signálov. Dôvodom je to, že počet signálov sa môže líšiť podľa systému, ale význam mien bude štandardný.

Makro NSIG je celkový počet definovaných signálov. Hodnota NSIG je o jeden väčší ako celkový počet definovaných signálov (všetky čísla signálov sú pridelené postupne).

Nasledujú štandardné signály:

Názov signálu Popis
PAMIATOK Zaveste proces. Signál SIGHUP sa používa na hlásenie odpojenia terminálu používateľa, pravdepodobne preto, že sa stratilo alebo zavesilo vzdialené pripojenie.
SIGINT Prerušte proces. Keď užívateľ napíše znak INTR (zvyčajne Ctrl + C), odošle sa signál SIGINT.
SIGQUIT Ukončite proces. Keď užívateľ napíše znak QUIT (zvyčajne Ctrl + \), odošle sa signál SIGQUIT.
SIGILL Protiprávne poučenie. Pri pokuse o vykonanie smeti alebo privilegovanej inštrukcie sa vygeneruje signál SIGILL. Program SIGILL sa dá vygenerovať aj pri pretečení zásobníka alebo pri problémoch so spustením obslužného programu signálu.
SIGTRAP Stopová pasca. Inštrukcia prerušenia a iná inštrukcia pasce vygeneruje signál SIGTRAP. Debugger používa tento signál.
SIGABRT Prerušiť. Signál SIGABRT sa generuje pri volaní funkcie abort (). Tento signál označuje chybu, ktorá je detekovaná samotným programom a hlásená volaním funkcie abort ().
SIGFPE Výnimka s pohyblivou rádovou čiarkou. Keď sa vyskytla závažná aritmetická chyba, vygeneruje sa signál SIGFPE.
SIGUSR1 a SIGUSR2 Signály SIGUSR1 a SIGUSR2 môžu byť použité podľa vášho želania. Je užitočné napísať im obslužný program signálu do programu, ktorý prijíma signál na jednoduchú medziprocesovú komunikáciu.

Predvolená akcia signálov

Každý signál má predvolenú akciu, jednu z nasledujúcich:

Termín: Proces sa ukončí.
Jadro: Proces sa ukončí a vytvorí sa súbor s výpisom jadra.
Ign: Proces bude signál ignorovať.
Stop: Proces sa zastaví.
Pokračovanie: Proces bude pokračovať až do zastavenia.

Predvolenú akciu je možné zmeniť pomocou funkcie obsluhy. Predvolenú akciu niektorých signálov nie je možné zmeniť. SIGKILL a SIGABRT Predvolenú akciu signálu nie je možné zmeniť alebo ignorovať.

Manipulácia so signálom

Ak proces prijíma signál, má pre tento druh signálu voľbu akcie. Proces môže ignorovať signál, môže určiť funkciu obslužného programu alebo prijať predvolenú akciu pre tento druh signálu.

Signál môžeme spracovať pomocou signál alebo sigakcia funkcia. Tu vidíme, ako najjednoduchšie signál () funkcia sa používa na spracovanie signálov.

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

The signál () zavolá func funkcia, ak proces prijíma signál signum. The signál () vráti ukazovateľ do funkcie func ak je úspešný, alebo vráti chybu errno a -1 inak.

The func ukazovateľ môže mať tri hodnoty:

  1. SIG_DFL: Je to ukazovateľ na predvolenú funkciu systému SIG_DFL (), deklarované v h hlavičkový súbor. Používa sa na vykonanie predvolenej akcie signálu.
  2. SIG_IGN: Je to ukazovateľ na funkciu ignorovania systému SIG_IGN (),deklarované v h hlavičkový súbor.
  3. Užívateľom definovaný ukazovateľ funkcie obsluhy: Používateľom definovaný typ funkcie obslužnej rutiny je void (*) (int), znamená návratový typ je neplatný a jeden argument typu int.

Základný príklad obsluhy signálu

#include
#include
#include
void sig_handler (int signum)
// Návratový typ funkcie handlera by mal byť neplatný
printf ("\ nInterná obslužná funkcia \ n");

int main ()
signál (SIGINT, sig_handler); // Zaregistrujte obsluhu signálu
for (int i = 1 ;; i ++) // Nekonečná slučka
printf ("% d: Vnútri hlavnej funkcie \ n", i);
spánok (1); // Oneskorenie o 1 sekundu

návrat 0;

Na snímke obrazovky s výstupom z Príkladu 1.c, môžeme vidieť, že v hlavnej funkcii sa vykonáva nekonečná slučka. Keď užívateľ zadá Ctrl + C, vyvolá sa zastavenie vykonávania hlavnej funkcie a funkcia obsluhy signálu. Po dokončení funkcie obsluhy sa obnovilo vykonávanie hlavnej funkcie. Keď používateľ zadá Ctrl + \, proces sa ukončí.

Príklad ignorovania signálov

#include
#include
#include
int main ()
signál (SIGINT, SIG_IGN); // Zaregistrujte obslužný program signálu na ignorovanie signálu
for (int i = 1 ;; i ++) // Nekonečná slučka
printf ("% d: Vnútri hlavnej funkcie \ n", i);
spánok (1); // Oneskorenie o 1 sekundu

návrat 0;

Tu je funkcia obsluhy zaregistrovaná do SIG_IGN () funkcia na ignorovanie činnosti signálu. Keď teda používateľ zadal Ctrl + C,  SIGINT signál sa generuje, ale akcia je ignorovaná.

Príklad registrácie registrátora signálu

#include
#include
#include
void sig_handler (int signum)
printf ("\ nInterná obslužná funkcia \ n");
signál (SIGINT, SIG_DFL); // Znova zaregistrovať obslužný program signálu pre predvolenú akciu

int main ()
signál (SIGINT, sig_handler); // Zaregistrujte obsluhu signálu
for (int i = 1 ;; i ++) // Nekonečná slučka
printf ("% d: Vnútri hlavnej funkcie \ n", i);
spánok (1); // Oneskorenie o 1 sekundu

návrat 0;

Na snímke obrazovky s výstupom z príkladu 3.c, môžeme vidieť, že keď užívateľ prvýkrát napísal Ctrl + C, vyvolala sa funkcia handlera. Vo funkcii obsluhy sa obsluha signálu znovu zaregistruje do SIG_DFL pre predvolené pôsobenie signálu. Keď používateľ zadá klávesy Ctrl + C druhýkrát, proces sa ukončí, čo je predvolená akcia SIGINT signál.

Posielanie signálov:

Proces tiež môže explicitne posielať signály sebe alebo inému procesu. Na odosielanie signálov je možné použiť funkciu raise () a kill (). Obe funkcie sú deklarované v signáli.h hlavičkový súbor.

int raise (int signum)

Funkcia raise () použitá na odoslanie signálu signum do procesu volania (samotného). Vráti nulu, ak je úspešná, a nenulovú hodnotu, ak zlyhá.

int kill (pid_t pid, int signum)

Funkcia kill použitá na odoslanie signálu signum na proces alebo skupinu procesov špecifikovanú pid.

Príklad obsluhy signálu SIGUSR1

#include
#include
void sig_handler (int signum)
printf ("Funkcia Inside handler \ n");

int main ()
signál (SIGUSR1, sig_handler); // Zaregistrujte obsluhu signálu
printf ("Vnútorná hlavná funkcia \ n");
zvýšenie (SIGUSR1);
printf ("Vnútorná hlavná funkcia \ n");
návrat 0;

Tu proces posiela sám sebe signál SIGUSR1 pomocou funkcie raise ().

Raise with Kill Example Program

#include
#include
#include
void sig_handler (int signum)
printf ("Funkcia Inside handler \ n");

int main ()
pid_t pid;
signál (SIGUSR1, sig_handler); // Zaregistrujte obsluhu signálu
printf ("Vnútorná hlavná funkcia \ n");
pid = getpid (); // ID procesu samotného
zabiť (pid, SIGUSR1); // Pošlite SIGUSR1 sám sebe
printf ("Vnútorná hlavná funkcia \ n");
návrat 0;

Tu je proces odoslaný SIGUSR1 signál pre seba pomocou zabiť () funkcia. getpid () sa používa na získanie samotného ID procesu.

V nasledujúcom príklade uvidíme, ako komunikuje rodič a dieťa (Inter Process Communication) pomocou zabiť () a signálna funkcia.

Komunikácia rodiča a dieťaťa so signálmi

#include
#include
#include
#include
void sig_handler_parent (int signum)
printf ("Rodič: Prijal signál odpovede od dieťaťa \ n");

void sig_handler_child (int signum)
printf ("Dieťa: Prijal signál od rodiča \ n");
spánok (1);
kill (getppid (), SIGUSR1);

int main ()
pid_t pid;
if ((pid = vidlica ())<0)
printf ("Vidlica zlyhala \ n");
výstup (1);

/ * Podradený proces * /
else if (pid == 0)
signál (SIGUSR1, sig_handler_child); // Zaregistrujte obsluhu signálu
printf ("Dieťa: čaká na signál \ n");
pauza();

/ * Nadradený proces * /
else
signál (SIGUSR1, sig_handler_parent); // Zaregistrujte obsluhu signálu
spánok (1);
printf ("Rodič: odosielanie signálu dieťaťu \ n");
zabiť (pid, SIGUSR1);
printf ("Rodič: čaká na odpoveď \ n");
pauza();

návrat 0;

Tu, vidlička() funkcia vytvorí podradený proces a vráti nulu do podradeného procesu a ID podradeného procesu do nadradeného procesu. Takže bolo skontrolované pid, aby sa rozhodlo o procese rodiča a dieťaťa. V rodičovskom procese je spánok 1 sekundu, aby podradený proces mohol zaregistrovať funkciu obsluhy signálu a čakať na signál od rodiča. Po 1 sekunde nadradený proces odoslať SIGUSR1 signál dieťaťu a počkajte na signál odozvy od dieťaťa. V podradenom procese najskôr čaká na signál od rodiča a po prijatí signálu sa vyvolá funkcia obsluhy. Z funkcie handler pošle podradený proces ďalší SIGUSR1 signál rodičovi. Tu getppid () funkcia sa používa na získanie ID rodičovského procesu.

Záver

Signál v systéme Linux je veľká téma. V tomto článku sme videli, ako zvládnuť signál od úplného základu, a tiež získať vedomosti o tom, ako sa signál generuje, ako môže proces posielať signál sám sebe a iným procesom, ako sa dá signál použiť na medziprocesovú komunikáciu.

WinMouse vám umožňuje prispôsobiť a vylepšiť pohyb ukazovateľa myši na počítači so systémom Windows
Ak chcete vylepšiť predvolené funkcie kurzora myši, použite freeware WinMouse. Pridáva ďalšie funkcie, ktoré vám pomôžu vyťažiť zo svojej skromnej myš...
Tlačidlo ľavého kliknutia myši nefunguje v systéme Windows 10
Ak používate samostatnú myš s prenosným počítačom alebo stolovým počítačom, ale nefunguje ľavé tlačidlo myši vo Windows 10/8/7 z nejakého dôvodu uvádz...
Kurzor pri písaní v systéme Windows 10 skáče alebo sa pohybuje náhodne
Ak zistíte, že kurzor myši skáče alebo sa pohybuje sám, automaticky a náhodne pri písaní na notebooku alebo počítači so systémom Windows, niektoré z t...