C programavimas

Kaip naudotis signalo tvarkytuvais C kalba?

Kaip naudotis signalo tvarkytuvais C kalba?
Šiame straipsnyje mes jums parodysime, kaip naudoti signalo tvarkytuvus sistemoje „Linux“ naudojant C kalbą. Bet pirmiausia aptarsime, kas yra signalas, kaip jis generuos keletą bendrų signalų, kuriuos galite naudoti savo programoje, o tada pažiūrėsime, kaip programa gali vykdyti įvairius signalus, kol programa vykdoma. Taigi, pradėkime.

Signalas

Signalas yra įvykis, generuojamas pranešti procesui ar gijai, kad įvyko kokia nors svarbi situacija. Kai procesas ar gija gauna signalą, procesas ar gija sustabdys jo veikimą ir imsis tam tikrų veiksmų. Signalas gali būti naudingas bendraujant tarp procesų.

Standartiniai signalai

Signalai yra apibrėžti antraštės faile signalas.h kaip makro konstanta. Signalo pavadinimas prasidėjo „SIG“, po kurio pateiktas trumpas signalo aprašymas. Taigi, kiekvienas signalas turi unikalią skaitinę vertę. Jūsų programa visada turėtų naudoti signalų pavadinimą, o ne signalų skaičių. Priežastis yra tai, kad signalo skaičius gali skirtis priklausomai nuo sistemos, tačiau vardų reikšmė bus standartinė.

Makrokomanda NSIG yra bendras apibrėžto signalo skaičius. Vertė NSIG yra vienas didesnis nei bendras apibrėžto signalo skaičius (visi signalo numeriai paskirstomi iš eilės).

Toliau pateikiami standartiniai signalai:

Signalo pavadinimas apibūdinimas
SIGHUP Pakabinkite procesą. Signalas „SIGHUP“ naudojamas pranešti apie vartotojo terminalo atjungimą, galbūt dėl ​​to, kad nutrūko nuotolinis ryšys arba jis užmezgė ryšį.
ŽENKLAS Nutraukite procesą. Kai vartotojas įveda INTR simbolį (paprastai „Ctrl“ + C), siunčiamas SIGINT signalas.
SIGQUIT Išeikite iš proceso. Kai vartotojas įveda simbolį QUIT (paprastai „Ctrl“ + \), siunčiamas „SIGQUIT“ signalas.
SIGILL Neteisėtas nurodymas. Kai bandoma vykdyti šiukšles ar privilegijuotas instrukcijas, generuojamas SIGILL signalas. Be to, SIGILL gali būti sukurtas, kai kaminas perpildomas arba kai sistemai kyla problemų paleidžiant signalo tvarkytuvą.
SIGTRAP Pėdsakų gaudyklė. Nutraukimo taško instrukcija ir kita gaudyklės instrukcija sugeneruos SIGTRAP signalą. Derintojas naudoja šį signalą.
SIGABRT Nutraukti. SIGABRT signalas generuojamas iškvietus abort () funkciją. Šis signalas rodo klaidą, kurią aptiko pati programa ir apie kurią praneša funkcijos nutraukimo () skambutis.
SIGFPE Kintamojo taško išimtis. Kai įvyko lemtinga aritmetinė klaida, generuojamas SIGFPE signalas.
SIGUSR1 ir SIGUSR2 Signalai SIGUSR1 ir SIGUSR2 gali būti naudojami kaip norite. Jiems naudinga parašyti signalo tvarkytuvą programoje, kuri priima signalą paprastam tarpprocesiniam bendravimui.

Numatytasis signalų veiksmas

Kiekvienas signalas turi numatytąjį veiksmą, vieną iš šių veiksmų:

Terminas: Procesas baigsis.
Šerdis: Procesas bus nutrauktas ir bus sukurtas pagrindinis iškelties failas.
Ignas: Procesas ignoruos signalą.
Sustabdyti: Procesas sustos.
Tęsinys: Procesas ir toliau bus sustabdytas.

Numatytasis veiksmas gali būti pakeistas naudojant „Handler“ funkciją. Negalima pakeisti numatytojo signalo veiksmo. SIGKILL ir SIGABRT signalo numatytojo veiksmo negalima pakeisti ar ignoruoti.

Signalų valdymas

Jei procesas gauna signalą, procesas gali pasirinkti tokio tipo signalą. Procesas gali ignoruoti signalą, gali nurodyti tvarkytuvo funkciją arba priimti numatytąjį veiksmą tokiam signalui.

Mes galime valdyti signalą naudodami signalas arba reikšmingumas funkcija. Čia mes matome, kaip paprasčiausias signalas () funkcija naudojama signalams valdyti.

int signalas () (int signum, negaliojantis (* func) (int))

The signalas () paskambins func funkcija, jei procesas gauna signalą signum. The signalas () grąžina rodyklę veikti func jei pavyksta arba ji grąžina klaidą klaidai ir -1 kitaip.

The func žymeklis gali turėti tris reikšmes:

  1. SIG_DFL: Tai yra sistemos numatytosios funkcijos rodyklė SIG_DFL (), paskelbta h antraštės failas. Jis naudojamas numatytam signalo veiksmui atlikti.
  2. SIG_IGN: Tai rodo, kad sistema nepaiso funkcijos SIG_IGN (),paskelbta h antraštės failas.
  3. Vartotojo apibrėžtas tvarkytuvo funkcijos rodyklė: Vartotojo apibrėžtas tvarkytuvo funkcijos tipas yra negaliojantis (*) (int), reiškia, kad grąžinimo tipas yra negaliojantis ir vienas int tipo argumentas.

Pagrindinis signalo tvarkytuvo pavyzdys

# įtraukti
# įtraukti
# įtraukti
negaliojantis sig_handler (int signum)
// Handler funkcijos grąžinimo tipas turėtų būti negaliojantis
printf ("\ nVidaus valdymo funkcija \ n");

int main ()
signalas (SIGINT, sig_handler); // Registruokite signalo tvarkytuvą
for (int i = 1 ;; i ++) // Begalinė kilpa
printf ("% d: Viduje pagrindinė funkcija \ n", i);
miegas (1); // Vėluoja 1 sekundę

grąžinti 0;

1 pavyzdžio išvesties ekrane.c, matome, kad pagrindinėje funkcijoje vykdoma begalinė kilpa. Vartotojui įvedus „Ctrl“ + C, pagrindinės funkcijos vykdymas sustabdomas ir iškviečiama signalo apdorojimo funkcija. Baigus tvarkytuvo funkciją, pagrindinė funkcija buvo atnaujinta. Kai vartotojo tipas įveda „Ctrl + \“, procesas baigiamas.

Ignoruoti signalų pavyzdį

# įtraukti
# įtraukti
# įtraukti
int main ()
signalas (SIGINT, SIG_IGN); // Registruokite signalo tvarkytuvą, kad ignoruotų signalą
for (int i = 1 ;; i ++) // Begalinė kilpa
printf ("% d: Viduje pagrindinė funkcija \ n", i);
miegas (1); // Vėluoja 1 sekundę

grąžinti 0;

Čia tvarkytuvo funkcija registruojama SIG_IGN () signalo veiksmo ignoravimo funkcija. Taigi, kai vartotojas įveda Ctrl + C,  ŽENKLAS signalas generuojamas, tačiau veiksmo nepaisoma.

Perregistruokite signalo tvarkytuvo pavyzdį

# įtraukti
# įtraukti
# įtraukti
negaliojantis sig_handler (int signum)
printf ("\ nVidaus valdymo funkcija \ n");
signalas (SIGINT, SIG_DFL); // Iš naujo užregistruokite signalo tvarkytuvą numatytam veiksmui

int main ()
signalas (SIGINT, sig_handler); // Registruokite signalo tvarkytuvą
for (int i = 1 ;; i ++) // Begalinė kilpa
printf ("% d: Viduje pagrindinė funkcija \ n", i);
miegas (1); // Vėluoja 1 sekundę

grąžinti 0;

3 pavyzdžio išvesties ekrane.c, matome, kad vartotojui pirmą kartą įvedus „Ctrl“ + C, iškviečiama „Handler“ funkcija. Naudodamas „Handler“ funkciją, signalo tvarkytuvas vėl registruojasi SIG_DFL numatytam signalo veiksmui. Kai vartotojas antrą kartą įveda „Ctrl“ + C, procesas yra nutrauktas, o tai yra numatytasis veiksmas ŽENKLAS signalas.

Siunčiami signalai:

Procesas taip pat gali aiškiai siųsti signalus sau ar kitam procesui. signalo siuntimui gali būti naudojama funkcija pakelti () ir nužudyti (). Abi funkcijos yra deklaruojamos signalu.h antraštės failas.

int pakelti (int signum)

Signalo siuntimui naudojama pakėlimo () funkcija signum į pašaukimo procesą (patį). Jei pavyksta, ji grąžina nulį, o jei nepavyksta, - nulinės vertės.

int nužudyti (pid_t pid, int signum)

Nužudymo funkcija, naudojama signalui siųsti signum į procesą ar procesų grupę, nurodytą pid.

SIGUSR1 signalo tvarkytuvo pavyzdys

# įtraukti
# įtraukti
negaliojantis sig_handler (int signum)
printf ("Vidinio tvarkytuvo funkcija \ n");

int main ()
signalas (SIGUSR1, sig_handler); // Registruokite signalo tvarkytuvą
printf ("Viduje pagrindinė funkcija \ n");
pakelti (SIGUSR1);
printf ("Viduje pagrindinė funkcija \ n");
grąžinti 0;

Čia procesas siunčia SIGUSR1 signalą sau, naudodamas „raise“) funkciją.

Pakelkite naudodamiesi nužudymo pavyzdžiu

# įtraukti
# įtraukti
# įtraukti
negaliojantis sig_handler (int signum)
printf ("Vidinio tvarkytuvo funkcija \ n");

int main ()
pid_t pid;
signalas (SIGUSR1, sig_handler); // Registruokite signalo tvarkytuvą
printf ("Viduje pagrindinė funkcija \ n");
pid = getpid (); // Pati proceso ID
nužudyti (pid, SIGUSR1); // Siųsti SIGUSR1 sau
printf ("Viduje pagrindinė funkcija \ n");
grąžinti 0;

Čia procesas siunčiamas SIGUSR1 signalą sau naudojant nužudyti () funkcija. getpid () naudojamas norint gauti proceso ID.

Kitame pavyzdyje pamatysime, kaip tėvų ir vaikų procesai bendrauja (tarpprocesinė komunikacija) nužudyti () ir signalo funkcija.

Tėvų vaiko bendravimas su signalais

# įtraukti
# įtraukti
# įtraukti
# įtraukti
negaliojantis sig_handler_parent (int signum)
printf ("Tėvas: gavo atsakymo signalą iš vaiko \ n");

negaliojantis sig_handler_child (int signum)
printf ("Vaikas: gavo signalą iš tėvų \ n");
miegas (1);
nužudyti (getppid (), SIGUSR1);

int main ()
pid_t pid;
jei ((pid = šakutė ())<0)
printf ("Šakė nepavyko \ n");
išėjimas (1);

/ * Vaiko procesas * /
dar jei (pid == 0)
signalas (SIGUSR1, sig_handler_child); // Registruokite signalo tvarkytuvą
printf ("Vaikas: laukia signalo \ n");
Pauzė();

/ * Tėvų procesas * /
Kitas
signalas (SIGUSR1, sig_handler_parent); // Registruokite signalo tvarkytuvą
miegas (1);
printf ("Tėvas: siunčia signalą vaikui \ n");
nužudyti (pid, SIGUSR1);
printf ("Tėvas: laukia atsakymo \ n");
Pauzė();

grąžinti 0;

Čia, šakutė () funkcija sukuria vaiko procesą ir grąžina nulį vaiko procesui ir vaiko proceso ID pirminiam procesui. Taigi, pid buvo patikrinta, kad būtų nuspręsta apie tėvų ir vaikų procesą. Tėvų procese jis miega 1 sekundę, kad vaikas galėtų užregistruoti signalo tvarkytojo funkciją ir laukti signalo iš tėvų. Po 1 sekundės pirminis procesas išsiųsti SIGUSR1 signalas vaikui procesas ir laukti atsakymo signalo iš vaiko. Vaiko procese pirmiausia laukiama signalo iš tėvų, o kai signalas gaunamas, iškviečiama tvarkytojo funkcija. Iš tvarkytojo funkcijos vaiko procesas siunčia kitą SIGUSR1 signalas tėvams. Čia getppid () funkcija naudojama norint gauti pirminio proceso ID.

Išvada

Signalas „Linux“ yra didelė tema. Šiame straipsnyje mes matėme, kaip elgtis su pačiu signalu, taip pat sužinojome, kaip signalas generuoja, kaip procesas gali siųsti signalą sau ir kitam procesui, kaip signalas gali būti naudojamas tarpprocesinei komunikacijai.

Atvirojo kodo komercinių žaidimų variklių uostai
Nemokami atvirojo kodo ir įvairių platformų žaidimų varikliai gali būti naudojami žaidžiant senus ir kai kuriuos gana naujus žaidimų pavadinimus. Šiam...
Geriausi „Linux“ komandinės eilutės žaidimai
Komandų eilutė yra ne tik jūsų didžiausias sąjungininkas naudojant „Linux“, bet ir pramogų šaltinis, nes ją galite naudoti norėdami žaisti daug įdomių...
Geriausios „Linux“ skirtos „Gamepad“ žemėlapių sudarymo programos
Jei jums patinka žaisti žaidimus „Linux“ su žaidimų pultu, o ne įprasta klaviatūra ir pelės įvesties sistema, yra keletas jums naudingų programų. Daug...