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.
- Jei nurodyto signalo veiksmo nepaisoma, signalas nedelsiant atmetamas.
- Programa gali užregistruoti tvarkytuvo funkciją naudodama tokią funkciją kaip signalas arba reikšmingumas. Tai vadinama prižiūrėtoju, kuris gaudo signalą.
- Jei signalas nebuvo nei tvarkomas, nei ignoruojamas, atliekamas numatytasis jo veiksmas.
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:
- SIG_DFL: Tai yra sistemos numatytosios funkcijos rodyklė SIG_DFL (), paskelbta h antraštės failas. Jis naudojamas numatytam signalo veiksmui atlikti.
- SIG_IGN: Tai rodo, kad sistema nepaiso funkcijos SIG_IGN (),paskelbta h antraštės failas.
- 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.