Jel
A jel egy olyan esemény, amelyet azért hoznak létre, hogy értesítsenek egy folyamatot vagy szálat arról, hogy valamilyen fontos helyzet érkezett. Amikor egy folyamat vagy szál jelet kapott, a folyamat vagy szál leállítja a tevékenységét, és megtesz bizonyos lépéseket. A jel hasznos lehet a folyamatok közötti kommunikációban.
Standard jelek
A jeleket a fejlécfájl határozza meg jelzés.h makróállandóként. A jel neve SIG -vel kezdődik, majd a jel rövid leírása következik. Tehát minden jelnek egyedi számértéke van. A program mindig a jelek nevét használja, nem a jelek számát. Ennek oka az, hogy a jelszám rendszer szerint eltérő lehet, de a nevek jelentése szabványos lesz.
A makró NSIG a definiált jelek teljes száma. Az értéke NSIG eggyel nagyobb, mint a definiált összes jel (Minden jelszámot egymás után osztanak ki).
A szabványos jelek a következők:
Jel neve | Leírás |
SIGHUP | Tegye le a folyamatot. A SIGHUP jel a felhasználói terminál szétkapcsolásának jelentésére szolgál, valószínűleg azért, mert egy távoli kapcsolat megszakad vagy leáll. |
JEL | A folyamat megszakítása. Amikor a felhasználó beírja az INTR karaktert (általában Ctrl + C), a rendszer elküldi a SIGINT jelet. |
SIGQUIT | Hagyja abba a folyamatot. Amikor a felhasználó beírja a QUIT karaktert (általában Ctrl + ), a SIGQUIT jel kerül elküldésre. |
FÓKA | Illegális utasítás. Amikor szemetet vagy kiváltságos utasítást próbál végrehajtani, a SIGILL jel generálódik. Ezenkívül a SIGILL akkor is előállítható, ha a verem túlcsordul, vagy ha a rendszernek problémái vannak a jelkezelő futtatásával. |
SIGTRAP | Nyomkövető csapda. Egy töréspont utasítás és más csapda utasítás generálja a SIGTRAP jelet. A hibakereső ezt a jelet használja. |
SIGABRT | Elvetél. A SIGABRT jel az abort () függvény meghívásakor keletkezik. Ez a jel azt a hibát jelzi, amelyet maga a program észlelt, és amelyet az abort () függvényhívás jelent. |
SIGFPE | Lebegőpontos kivétel. Végzetes számtani hiba esetén a SIGFPE jel generálódik. |
SIGUSR1 és SIGUSR2 | A SIGUSR1 és SIGUSR2 jelek tetszés szerint használhatók. Hasznos, ha jelfeldolgozót írunk nekik a programba, amely fogadja a jelet az egyszerű folyamatközi kommunikációhoz. |
A jelek alapértelmezett művelete
Minden jelnek van egy alapértelmezett művelete, az alábbiak egyike:
Időtartam: A folyamat leáll.
Mag: A folyamat leáll, és létrehoz egy alapvető dump fájlt.
Ign: A folyamat figyelmen kívül hagyja a jelet.
Álljon meg: A folyamat leáll.
Fiók: A folyamat leállításától folytatódik.
Az alapértelmezett művelet megváltoztatható a kezelő funkcióval. Néhány jel alapértelmezett művelete nem módosítható. SIGKILL és SIGABRT a jel alapértelmezett művelete nem módosítható vagy figyelmen kívül hagyható.
Jelkezelés
Ha egy folyamat jelet kap, a folyamat választhat az adott jelhez tartozó cselekvéshez. A folyamat figyelmen kívül hagyhatja a jelet, megadhat egy kezelő funkciót, vagy elfogadhatja az alapértelmezett műveletet az ilyen típusú jelhez.
- Ha a jel adott műveletét figyelmen kívül hagyja, akkor a jelet azonnal elveti.
- A program regisztrálhat egy kezelő funkciót a funkció használatával, mint pl jel vagy sigaction . Ezt hívják kezelőnek, amely elkapja a jelet.
- Ha a jelet nem kezelték és nem vették figyelmen kívül, akkor az alapértelmezett műveletre kerül sor.
A jelet a segítségével kezelhetjük jel vagy sigaction funkció. Itt láthatjuk, hogy a legegyszerűbb jel() funkció a jelek kezelésére szolgál.
intjel() (intjel, üres (*funkció)(int))Az jel() hívni fogja a funkció funkció, ha a folyamat jelet kap jel . Az jel() mutatót ad vissza a függvényhez funkció ha sikeres, vagy hibát ad vissza errno -nak, és -1 -et.
Az funkció a mutatónak három értéke lehet:
- SIG_DFL : Ez egy mutató a rendszer alapértelmezett funkciójára SIG_DFL () , kijelentette h fejléc fájl. A jel alapértelmezett műveletének végrehajtására szolgál.
- SIG_IGN : Ez egy mutató a rendszer figyelmen kívül hagyására SIG_IGN () , kijelentette h fejléc fájl.
- A felhasználó által meghatározott kezelő funkciómutató : A felhasználó által meghatározott kezelő funkciótípus a érvénytelen (*) (int) , azt jelenti, hogy a visszatérési típus érvénytelen, és egy int típusú argumentum.
Alapvető jelkezelő példa
#befoglalni#befoglalni
#befoglalni
üressig_handler(intjel){
// A kezelő függvény visszatérési típusának érvénytelennek kell lennie
printf (' nBelső kezelő funkció n');
}
intfő-(){
jel(JEL,sig_handler); // Regisztrációs jelkezelő
számára(intén=1;;én++){ // Végtelen ciklus
printf ('%d: Belül a fő funkció n',én);
alvás(1); // Késleltetés 1 másodpercig
}
Visszatérés 0;
}
A példa 1.c kimenetének képernyőképén láthatjuk, hogy a főfunkcióban végtelen ciklus fut. Amikor a felhasználó beírta a Ctrl+C billentyűt, a fő funkció végrehajtása leáll, és a jel kezelő funkciója meghívásra kerül. A kezelő funkció befejezése után a fő funkció végrehajtása folytatódott. Amikor a felhasználói típus beírta a Ctrl+ billentyűt, a folyamat kilép.
Példa a jelek figyelmen kívül hagyására
#befoglalni#befoglalni
#befoglalni
intfő-(){
jel(JEL,SIG_IGN); // Regisztrálja a jelkezelőt a jel figyelmen kívül hagyására
számára(intén=1;;én++){ // Végtelen ciklus
printf ('%d: Belül a fő funkció n',én);
alvás(1); // Késleltetés 1 másodpercig
}
Visszatérés 0;
}
Itt a kezelő funkció a regisztráció SIG_IGN () funkció a jeltovábbítás figyelmen kívül hagyására. Tehát amikor a felhasználó beírta a Ctrl+C billentyűt, JEL jel generál, de a műveletet figyelmen kívül hagyja.
Példa az újraregisztrált jelkezelőre
#befoglalni#befoglalni
#befoglalni
üressig_handler(intjel){
printf (' nBelső kezelő funkció n');
jel(JEL,SIG_DFL); // Regisztrálja újra a jelkezelőt az alapértelmezett művelethez
}
intfő-(){
jel(JEL,sig_handler); // Regisztrációs jelkezelő
számára(intén=1;;én++){ // Végtelen ciklus
printf ('%d: Belül a fő funkció n',én);
alvás(1); // Késleltetés 1 másodpercig
}
Visszatérés 0;
}
A példa 3.c kimenetének képernyőképén láthatjuk, hogy amikor a felhasználó először beírta a Ctrl+C billentyűt, a kezelő függvény meghívott. A kezelő funkcióban a jelkezelő újra regisztrál a SIG_DFL a jel alapértelmezett működéséhez. Amikor a felhasználó másodszor írta be a Ctrl+C billentyűt, a folyamat befejeződik, ami az alapértelmezett művelet JEL jel.
Jelzések küldése:
Egy folyamat kifejezetten jeleket is küldhet magának vagy egy másik folyamatnak. az emelési () és a kill () függvény használható jelek küldésére. Mindkét funkciót a signal.h fejlécfájl tartalmazza.
int emel (intjel)A jel küldésére használt emelési () függvény jel a hívási folyamathoz (magához). Ha sikeres, akkor nullát ad vissza, és ha nem, nulla értéket ad vissza.
intmegöl(pid_t pid, intjel)A jel küldésére használt kill funkció jel által meghatározott folyamathoz vagy folyamatcsoporthoz pid .
Példa a SIGUSR1 jelkezelőre
#befoglalni#befoglalni
üressig_handler(intjel){
printf ('Belső kezelő funkció n');
}
intfő-(){
jel(SIGUSR1,sig_handler); // Regisztrációs jelkezelő
printf ('Belül a fő funkció n');
emel (SIGUSR1);
printf ('Belül a fő funkció n');
Visszatérés 0;
}
Itt a folyamat SIGUSR1 jelet küld magának a raise () függvény használatával.
Emelj Kill Example Programmal
#befoglalni#befoglalni
#befoglalni
üressig_handler(intjel){
printf ('Belső kezelő funkció n');
}
intfő-(){
pid_t pid;
jel(SIGUSR1,sig_handler); // Regisztrációs jelkezelő
printf ('Belül a fő funkció n');
pid=hülye(); // Folyamat azonosítója
megöl(pid,SIGUSR1); // Küldje el magának a SIGUSR1 -et
printf ('Belül a fő funkció n');
Visszatérés 0;
}
Itt a folyamat küld SIGUSR1 jelzi önmagának a használatával megöl() funkció. hülye () a folyamat azonosítójának lekérésére szolgál.
A következő példában látni fogjuk, hogyan kommunikálnak a szülő és a gyermek folyamatai (Inter Process Communication) megöl() és jel funkció.
Szülő gyermek kommunikáció jelekkel
#befoglalni#befoglalni
#befoglalni
#befoglalni
üressig_handler_parent(intjel){
printf ('Szülő: Válaszjelet kapott a gyerektől n');
}
üressig_handler_child(intjel){
printf ('Gyermek: Jelt kapott a szülőktől n');
alvás(1);
megöl(kapaszkodó(),SIGUSR1);
}
intfő-(){
pid_t pid;
ha((pid=Villa())<0){
printf ('Nem sikerült a villa n');
kijárat (1);
}
/ * Gyermekfolyamat */
más ha(pid==0){
jel(SIGUSR1,sig_handler_child); // Regisztrációs jelkezelő
printf ('Gyermek: jelre vár n');
szünet();
}
/ * Szülői folyamat */
más{
jel(SIGUSR1,sig_handler_parent); // Regisztrációs jelkezelő
alvás(1);
printf ('Szülő: jelet küld gyermeknek n');
megöl(pid,SIGUSR1);
printf ('Szülő: válaszra vár n');
szünet();
}
Visszatérés 0;
}
Itt, Villa() függvény létrehozza a gyermekfolyamatot, és nullát ad vissza a gyermekfolyamatnak, és a gyermekfolyamat -azonosítót a szülői folyamatnak. Tehát a pid ellenőrzésre került, hogy eldöntse a szülő és a gyermek folyamatát. A szülői folyamatban 1 másodpercig alszik, hogy a gyermekfolyamat regisztrálja a jelfeldolgozó funkciót, és várja meg a szülő jeleit. 1 másodperces szülői folyamat után küldjön SIGUSR1 jelezze a gyermeknek a folyamatot, és várja meg a gyermek válaszjelét. A gyermekfolyamatban először a szülői jelre vár, és amikor jel érkezik, a kezelő funkció hívódik meg. A kezelő funkcióból a gyermekfolyamat küld egy másikat SIGUSR1 jelezni a szülőnek. Itt getppid () függvény a szülői folyamat azonosítójának lekérésére szolgál.
Következtetés
A jelzés Linuxon nagy téma. Ebben a cikkben láttuk, hogyan kell kezelni a jelet az alapoktól, és megismerhetjük azt is, hogy a jel hogyan keletkezik, hogyan küldhet egy folyamat jelet önmagának és más folyamatoknak, hogyan használható a jel a folyamatok közötti kommunikációhoz.