C programozás

A jelkezelők használata C nyelven?

A jelkezelők használata C nyelven?
Ebben a cikkben bemutatjuk, hogyan használhatja a jelkezelőket Linux alatt C nyelv használatával. De először megbeszéljük, mi a jel, hogyan generál néhány általános jelet, amelyet felhasználhat a programjában, majd megnézzük, hogyan kezelheti a program a különféle jeleket a program végrehajtása közben. Tehát kezdjük.

Jel

A jel olyan esemény, amelyet azért generálnak, hogy értesítsék a folyamatot vagy a szálat arról, hogy valamilyen fontos helyzet érkezett. Amikor egy folyamat vagy egy szál jelet kapott, a folyamat vagy a szál leállítja a működését, és valamilyen műveletet végrehajt. A jel hasznos lehet a folyamatok közötti kommunikációhoz.

Standard jelek

A jeleket a fejlécfájl határozza meg jel.h mint makroállandó. A jel neve „SIG” -vel kezdődött, amelyet a jel rövid leírása követett. Tehát minden jelnek egyedi számértéke van. A programnak mindig a jelek nevét kell használnia, nem a jelek számát. Ennek oka az, hogy a jelek száma rendszerenként eltérhet, de a nevek jelentése standard lesz.

A makró NSIG a definiált jel teljes száma. Az értéke NSIG eggyel nagyobb, mint a megadott jel teljes száma (az összes jelszámot egymás után osztják ki).

A következők a standard jelek:

Jel neve Leírás
SIGHUP Tegye le a folyamatot. A SIGHUP jel arra szolgál, hogy jelentse a felhasználó termináljának megszakadását, valószínűleg azért, mert egy távoli kapcsolat megszakadt vagy leteszi a kapcsolatot.
JEL Szakítsa meg a folyamatot. Amikor a felhasználó beírja az INTR karaktert (általában Ctrl + C), akkor a SIGINT jelet küldi.
SIGQUIT Lépjen ki a folyamatból. Amikor a felhasználó beírja a QUIT karaktert (általában Ctrl + \), akkor a SIGQUIT jelet küldi.
SIGILL Illegális utasítás. Ha szemetet vagy privilegizált utasítást próbál végrehajtani, akkor a SIGILL jel jön létre. A SIGILL akkor is létrehozható, amikor a verem túlcsordul, vagy ha a rendszernek problémái vannak egy jelkezelő futtatásával.
SIGTRAP Nyomcsapda. 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 akkor keletkezik, amikor az abort () függvényt meghívják. Ez a jel hibát jelez, amelyet maga a program észlelt, és amelyet az abort () függvényhívás jelentett.
SIGFPE Lebegőpontos kivétel. Végzetes számtani hiba esetén a SIGFPE jel jön létre.
SIGUSR1 és SIGUSR2 A SIGUSR1 és SIGUSR2 jelek tetszés szerint használhatók. Hasznos egy jelkezelőt írni nekik abba a programba, amely az egyszerű folyamatközi kommunikáció érdekében fogadja a jelet.

A jelek alapértelmezett művelete

Minden jelnek van egy alapértelmezett művelete, a következők egyikével:

Időtartam: A folyamat befejeződik.
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.
Cont: A folyamat továbbra is leáll.

Az alapértelmezett művelet a kezelő funkcióval megváltoztatható. Egyes jelek 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, akkor a folyamatnak választania kell a műveletet az adott jelhez. A folyamat figyelmen kívül hagyhatja a jelet, meghatározhat egy kezelő funkciót, vagy elfogadhatja az ilyen jel alapértelmezett műveletét.

A jelet használhatjuk jel vagy jelzés funkció. Itt láthatjuk, hogy a legegyszerűbb jel() funkció a jelek kezelésére szolgál.

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

A jel() felhívja a func funkció, ha a folyamat jelet kap signum. A jel() visszaad egy mutatót a működésére func ha sikeres, vagy hibát ad vissza az errno-ra, máskülönben -1-re.

A func A mutatónak három értéke lehet:

  1. SIG_DFL: Ez egy mutató a rendszer alapértelmezett funkciójára SIG_DFL (), -ban nyilatkozott h fejlécfájl. A jel alapértelmezett műveletére szolgál.
  2. SIG_IGN: Ez egy mutató a rendszer figyelmen kívül hagyására SIG_IGN (),-ban nyilatkozott h fejlécfájl.
  3. Felhasználó által meghatározott kezelő funkció mutató: A felhasználó által meghatározott kezelő funkció típusa érvénytelen (*) (int), azt jelenti, hogy a return típus érvénytelen, és az int típusú argumentum.

Alap jelfeldolgozó példa

#include
#include
#include
void sig_handler (int signum)
// A handler függvény visszatérési típusának érvénytelennek kell lennie
printf ("\ nBelső kezelő funkció \ n");

int main ()
jel (SIGINT, sig_handler); // Jelkezelő regisztrálása
for (int i = 1 ;; i ++) // Végtelen hurok
printf ("% d: Inside main function \ n", i);
alvás (1); // Késleltetés 1 másodpercig

visszatér 0;

Az 1. példa kimenetének képernyőképén.c, láthatjuk, hogy a fő funkcióban végtelen ciklus hajt végre. Amikor a felhasználó beírta a Ctrl + C billentyűkombináció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ó írja be a Ctrl + \ parancsot, a folyamat befejeződik.

Figyelmen kívül hagyja a jeleket

#include
#include
#include
int main ()
jel (SIGINT, SIG_IGN); // Jelzőkezelő regisztrálása a jel figyelmen kívül hagyása érdekében
for (int i = 1 ;; i ++) // Végtelen hurok
printf ("% d: Inside main function \ n", i);
alvás (1); // Késleltetés 1 másodpercig

visszatér 0;

Itt a kezelő funkció regisztrálva van SIG_IGN () funkció a jelzé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ódik, de a műveletet figyelmen kívül hagyják.

Újra regisztrálja a jelkezelő példát

#include
#include
#include
void sig_handler (int signum)
printf ("\ nBelső kezelő funkció \ n");
jel (SIGINT, SIG_DFL); // Újra regisztrálja a jelkezelőt alapértelmezett műveletre

int main ()
jel (SIGINT, sig_handler); // Jelkezelő regisztrálása
for (int i = 1 ;; i ++) // Végtelen hurok
printf ("% d: Inside main function \ n", i);
alvás (1); // Késleltetés 1 másodpercig

visszatér 0;

A 3. példa kimenetének képernyőképén.c, láthatjuk, hogy amikor a felhasználó először beírta a Ctrl + C billentyűkombinációt, a kezelő függvény meghívásra került. A kezelő funkcióban a jelkezelő újra regisztrál SIG_DFL a jel alapértelmezett műveletéhez. Amikor a felhasználó másodszor írja be a Ctrl + C billentyűkombinációt, a folyamat befejeződik, amely az alapértelmezett művelete JEL jel.

Jelek küldése:

Egy folyamat kifejezetten jeleket is küldhet önmagának vagy egy másik folyamatnak. A raise () és kill () függvény használható jelek küldésére. Mindkét funkció jelben van deklarálva.h fejlécfájl.

int emelés (int signum)

A jel küldéséhez használt emelés () funkció signum a hívási folyamathoz (magához). Ha sikeres, akkor nullát ad vissza, ha nem, akkor nem null értéket ad vissza.

int kill (pid_t pid, int signum)

A kill funkció a jel küldésére szolgál signum által meghatározott folyamathoz vagy folyamatcsoporthoz pid.

SIGUSR1 jelkezelő példa

#include
#include
void sig_handler (int signum)
printf ("Belső kezelő funkció \ n");

int main ()
jel (SIGUSR1, sig_handler); // Jelkezelő regisztrálása
printf ("Inside main function \ n");
emelés (SIGUSR1);
printf ("Inside main function \ n");
visszatér 0;

Itt a folyamat a SIGUSR1 jelet küldi magának a raise () függvény segítségével.

Emelés a Kill példaprogrammal

#include
#include
#include
void sig_handler (int signum)
printf ("Belső kezelő funkció \ n");

int main ()
pid_t pid;
jel (SIGUSR1, sig_handler); // Jelkezelő regisztrálása
printf ("Inside main function \ n");
pid = getpid (); // Folyamatazonosítója
kill (pid, SIGUSR1); // Küldje el a SIGUSR1-et magának
printf ("Inside main function \ n");
visszatér 0;

Itt a folyamat küldés SIGUSR1 jelet magának felhasználásával megöl() funkció. getpid () a folyamatazonosító megszerzésére szolgál.

A következő példában megnézzük, hogy a szülő és a gyermek hogyan kommunikál (Inter Process Communication) megöl() és a jel funkció.

A szülő gyermek kommunikációja a jelekkel

#include
#include
#include
#include
void sig_handler_parent (int signum)
printf ("Szülő: Válaszjelet kapott a gyermektől \ n");

void sig_handler_child (int signum)
printf ("Gyermek: Jelet kapott a szülőtől \ n");
alvás (1);
kill (getppid (), SIGUSR1);

int main ()
pid_t pid;
if ((pid = villa ())<0)
printf ("Sikertelen villa \ n");
kilépés (1);

/ * Gyermekfolyamat * /
else if (pid == 0)
jel (SIGUSR1, sig_handler_child); // Jelkezelő regisztrálása
printf ("Gyermek: jelre vár \ n");
szünet();

/ * Szülői folyamat * /
más
jel (SIGUSR1, sig_handler_szülő); // Jelkezelő regisztrálása
alvás (1);
printf ("Szülő: jel küldése Gyermeknek \ n");
kill (pid, SIGUSR1);
printf ("Szülő: válaszra vár \ n");
szünet();

visszatér 0;

Itt, Villa() függvény létrehozza a gyermek folyamatát, és nulla értéket ad vissza a gyermek folyamathoz, és a gyermek folyamat azonosítóját a szülő folyamathoz. Tehát, a pid ellenőrizte a szülő és a gyermek folyamatának eldöntését. A szülői folyamatban 1 másodpercig alszik, hogy a gyermek folyamat regisztrálja a jelkezelő funkciót, és megvárja a jelet a szülőtől. 1 másodperc után szülői folyamat küld SIGUSR1 jel a gyermeknek folyamat, és várja meg a gyermek válaszjelét. A gyermek folyamatban először a szülőktől érkező jelre vár, és amikor jel érkezik, a kezelő funkciót hívják meg. A kezelő funkcióból a gyermekfolyamat küld egy másikat SIGUSR1 jelzés a szülőnek. Itt getppid () függvény a szülő folyamatazonosító lekérésére szolgál.

Következtetés

A Linux alatt történő jelzés nagy téma. Ebben a cikkben láttuk, hogyan kell kezelni a jeleket az alapszinttől, és megismerhetjük azt is, hogy a jel hogyan keletkezik, hogyan képes egy folyamat jelet küldeni önmagának és más folyamatnak, hogyan lehet a jelet felhasználni a folyamatok közötti kommunikációra.

Az egér és az érintőpadok görgetési irányának megfordítása a Windows 10 rendszerben
Egér és Érintőpads nemcsak a számítást könnyűvé, de hatékonyabbá és kevésbé időigényessé is teszi. Nem tudunk elképzelni egy életet ezek nélkül az esz...
Az egérmutató és a kurzor méretének, színének és sémájának módosítása a Windows 10 rendszeren
Az egérmutató és a kurzor a Windows 10 operációs rendszerben nagyon fontos szempont. Ez elmondható más operációs rendszerekről is, tehát valójában eze...
Ingyenes és nyílt forráskódú játékmotorok a Linux játékok fejlesztéséhez
Ez a cikk felsorolja azokat az ingyenes és nyílt forráskódú játékmotorokat, amelyek felhasználhatók 2D és 3D játékok fejlesztésére Linuxon. Számos ily...