Signaal
Signaal on sündmus, mis genereeritakse protsessi või lõime teavitamiseks mõne olulise olukorra saabumisest. Kui protsess või lõim on signaali saanud, peatab protsess või lõim oma tegevuse ja võtab mõne toimingu. Signaal võib olla kasulik protsessidevaheliseks suhtlemiseks.
Standardsignaalid
Signaalid on määratletud päisefailis signaal.h makro konstandina. Signaali nimi algas tähega “SIG” ja sellele järgnes signaali lühikirjeldus. Seega on igal signaalil ainulaadne arvuline väärtus. Teie programm peaks alati kasutama signaalide nime, mitte signaalide numbrit. Põhjus on selles, et signaali number võib süsteemiti erineda, kuid nimede tähendus on standardne.
Makro NSIG on määratletud signaali koguarv. Väärtus NSIG on üks suurem kui määratletud signaali koguarv (kõik signaalinumbrid jagatakse järjestikku).
Järgmised on standardsignaalid:
Signaali nimi | Kirjeldus |
SIGHUP | Katkestage protsess. Signaali SIGHUP kasutatakse kasutaja terminali lahtiühendamisest teatamiseks, võib-olla seetõttu, et kaugühendus on kadunud või katkestab ühenduse. |
SIGINT | Katkestage protsess. Kui kasutaja sisestab märgi INTR (tavaliselt Ctrl + C), saadetakse signaal SIGINT. |
SIGQUIT | Lõpeta protsess. Kui kasutaja sisestab märgi QUIT (tavaliselt Ctrl + \), saadetakse signaal SIGQUIT. |
SIGILL | Ebaseaduslik juhendamine. Kui proovitakse täita prügi või privilegeeritud juhiseid, genereeritakse signaal SIGILL. Samuti saab SIGILL-i genereerida virna ülevoolamisel või kui süsteemil on probleeme signaalkäitleja käitamisega. |
SIGTRAP | Jäljepüünis. Murdepunkti käsk ja muud püünisjuhised genereerivad SIGTRAP signaali. Silur kasutab seda signaali. |
SIGABRT | Katkesta. Signaal SIGABRT genereeritakse, kui kutsutakse funktsioon abort (). See signaal näitab viga, mille programm ise tuvastab ja mille funktsioonikõne abort () teatab. |
SIGFPE | Ujuvate punktide erand. Saatusliku aritmeetilise vea tekkimisel genereeritakse signaal SIGFPE. |
SIGUSR1 ja SIGUSR2 | Signaale SIGUSR1 ja SIGUSR2 võidakse kasutada vastavalt teie soovile. Nende jaoks on kasulik kirjutada signaalkäitleja programmis, mis võtab signaali vastu lihtsaks protsessidevaheliseks suhtlemiseks. |
Signaalide vaiketoiming
Igal signaalil on vaiketoiming, üks järgmistest:
Termin: Protsess lõpeb.
Tuum: Protsess lõpetatakse ja luuakse tuumafail.
Ign: Protsess ignoreerib signaali.
Peatus: Protsess peatub.
Cont: Protsessi peatamine jätkub.
Vaiketoimingut saab muuta käitleja funktsiooni abil. Mõne signaali vaiketoimingut ei saa muuta. SIGKILL ja SIGABRT signaali vaiketoimingut ei saa muuta ega eirata.
Signaali käsitsemine
Kui protsess saab signaali, saab protsess seda tüüpi signaali jaoks valida toimingu. Protsess võib signaali ignoreerida, määrata käitleja funktsiooni või aktsepteerida sellist signaali vaiketoimingut.
- Kui signaali jaoks määratud toimingut ignoreeritakse, visatakse signaal kohe minema.
- Programm saab registreerida käitleja funktsiooni, kasutades funktsiooni nagu signaal või sigaction. Seda nimetatakse käitleja saab signaali kinni.
- Kui signaali pole käsitletud ega ignoreeritud, toimub selle vaiketoiming.
Saame signaaliga hakkama signaal või sigaction funktsioon. Siin näeme, kuidas kõige lihtsam signaal() funktsiooni kasutatakse signaalide käitlemiseks.
int signaal () (int signum, tühine (* func) (int))The signaal() helistab func funktsioon, kui protsess saab signaali signum. The signaal() tagastab kursori funktsiooni func kui see õnnestub või tagastab vea vigale ja muul juhul -1.
The func osutil võib olla kolm väärtust:
- SIG_DFL: See näitab süsteemi vaikefunktsiooni SIG_DFL (), aastal deklareeritud h päisefail. Seda kasutatakse signaali vaiketoimingute tegemiseks.
- SIG_IGN: See on osutus süsteemi ignoreerimiseks SIG_IGN (),aastal deklareeritud h päisefail.
- Kasutaja määratud käitleja funktsioonikursor: Kasutaja määratud käitleja funktsiooni tüüp on kehtetu (*) (int), tähendab, et tagasitüübi tüüp on tühine ja üks argumendi tüüp int.
Signaali käitleja põhinäide
# kaasata# kaasata
# kaasata
void sig_handler (int signum)
// Handleri funktsiooni Return tüüp peaks olema tühine
printf ("\ nSisese käitleja funktsioon \ n");
int main ()
signaal (SIGINT, sig_handler); // Registreerige signaalkäitleja
for (int i = 1 ;; i ++) // lõpmatu silmus
printf ("% d: sees põhifunktsioon \ n", i);
uni (1); // Viivitage 1 sekund
tagastama 0;
Näite1 väljundi ekraanipildil.c, näeme, et põhifunktsioonis käivitab lõpmatu silmus. Kui kasutaja sisestas Ctrl + C, peatub põhifunktsiooni täitmine ja käivitatakse signaali käitlejafunktsioon. Pärast käitleja funktsiooni täitmist jätkati põhifunktsiooni täitmist. Kui kasutaja tüüp sisestas Ctrl + \, protsess lõpetatakse.
Eirake signaali näidet
# kaasata# kaasata
# kaasata
int main ()
signaal (SIGINT, SIG_IGN); // Registreerige signaali käitleja signaali eiramiseks
for (int i = 1 ;; i ++) // lõpmatu silmus
printf ("% d: sees põhifunktsioon \ n", i);
uni (1); // Viivitage 1 sekund
tagastama 0;
Siin on käitleja funktsioon registreerida SIG_IGN () funktsioon signaali toimingu ignoreerimiseks. Niisiis, kui kasutaja sisestas Ctrl + C, SIGINT signaal genereeritakse, kuid toimingut ignoreeritakse.
Signalinkäitleja näide uuesti registreerimine
# kaasata# kaasata
# kaasata
void sig_handler (int signum)
printf ("\ nSisese käitleja funktsioon \ n");
signaal (SIGINT, SIG_DFL); // Registreerige signaalitöötleja uuesti vaiketoiminguks
int main ()
signaal (SIGINT, sig_handler); // Registreerige signaalkäitleja
for (int i = 1 ;; i ++) // lõpmatu silmus
printf ("% d: sees põhifunktsioon \ n", i);
uni (1); // Viivitage 1 sekund
tagastama 0;
Näite 3 väljundi ekraanipildil.c, näeme, et kui kasutaja sisestas esmakordselt Ctrl + C, kutsuti üles käitleja funktsioon. Käitleja funktsioonis registreerub signaalikäitleja uuesti SIG_DFL signaali vaiketoimingu jaoks. Kui kasutaja sisestas teist korda klahvikombinatsiooni Ctrl + C, lõpetatakse protsess, mis on faili vaiketoiming SIGINT signaal.
Signaalide saatmine:
Protsess võib selgesõnaliselt saata signaale endale või teisele protsessile. funktsiooni tõsta () ja tappa () saab kasutada signaalide saatmiseks. Mõlemad funktsioonid on deklareeritud signaalina.h päisefail.
int tõsta (int signum)Signaali saatmiseks kasutatav funktsioon lift () signum helistamisprotsessile (iseendale). See tagastab õnnestumise korral nulli ja ebaõnnestumise korral nullväärtuse.
int tapma (pid_t pid, int signum)Tapmise funktsioon, mida kasutatakse signaali saatmiseks signum määratud protsessile või protsessigrupile pid.
SIGUSR1 signaalkäitleja näide
# kaasata# kaasata
void sig_handler (int signum)
printf ("Sisemise käitleja funktsioon \ n");
int main ()
signaal (SIGUSR1, sig_handler); // Registreerige signaalkäitleja
printf ("Sees põhifunktsioon \ n");
tõsta (SIGUSR1);
printf ("Sees põhifunktsioon \ n");
tagastama 0;
Siin saadab protsess SIGUSR1 signaali endale, kasutades funktsiooni raise ().
Tõstke Kill Näidisprogrammiga
# kaasata# kaasata
# kaasata
void sig_handler (int signum)
printf ("Sisemise käitleja funktsioon \ n");
int main ()
pid_t pid;
signaal (SIGUSR1, sig_handler); // Registreerige signaalkäitleja
printf ("Sees põhifunktsioon \ n");
pid = getpid (); // Protsessi ID ise
tapma (pid, SIGUSR1); // Saada SIGUSR1 iseendale
printf ("Sees põhifunktsioon \ n");
tagastama 0;
Siin protsess saadetakse SIGUSR1 signaali endale kasutades tapma () funktsioon. getpid () kasutatakse enda protsessi ID saamiseks.
Järgmises näites näeme, kuidas vanema ja lapse protsessid suhtlevad (protsessidevaheline suhtlus) tapma () ja signaali funktsioon.
Vanemlapse suhtlus signaalidega
# kaasata# kaasata
# kaasata
# kaasata
void sig_handler_parent (int signum)
printf ("Vanem: sai lapselt vastussignaali \ n");
void sig_handler_child (int signum)
printf ("Laps: sai vanemalt signaali \ n");
uni (1);
tapma (getppid (), SIGUSR1);
int main ()
pid_t pid;
kui ((pid = kahvel ())<0)
printf ("Kahvel ebaõnnestus \ n");
väljapääs (1);
/ * Lapse protsess * /
muidu if (pid == 0)
signaal (SIGUSR1, sig_handler_child); // Registreerige signaalkäitleja
printf ("Laps: ootab signaali \ n");
paus ();
/ * Vanemprotsess * /
veel
signaal (SIGUSR1, sig_handler_vanem); // Registreerige signaalkäitleja
uni (1);
printf ("Vanem: signaali saatmine lapsele \ n");
tapma (pid, SIGUSR1);
printf ("Vanem: ootab vastust \ n");
paus ();
tagastama 0;
Siin, kahvel () Funktsioon loob lapseprotsessi ja tagastab lapseprotsessile nulli ja lapseprotsessi ID vanemprotsessile. Niisiis, pid on kontrollitud, et otsustada vanema ja lapse protsess. Vanemprotsessis magatakse seda 1 sekund, et lapsprotsess saaks registreerida signaalkäitleja funktsiooni ja oodata vanema signaali. Pärast 1 sekundit vanemprotsessi saatmine SIGUSR1 signaal lapsele ja oodake lapse reageerimissignaali. Lapseprotsessis ootab see kõigepealt vanema signaali ja signaali vastuvõtmisel käivitatakse käitleja funktsioon. Käitleja funktsioonist saadab lapseprotsess teise SIGUSR1 signaal vanemale. Siin getppid () funktsiooni kasutatakse vanemprotsessi ID hankimiseks.
Järeldus
Signaal Linuxis on suur teema. Selles artiklis oleme näinud, kuidas käsitseda signaali kõige põhilisemast, ning saada ka teadmisi signaali genereerimise kohta, kuidas protsess saab signaali saata iseendale ja muule protsessile, kuidas signaali saab kasutada protsessidevaheliseks suhtluseks.