Jel (IPC) - Signal (IPC)

A jelek egy szabványosított üzenetek, amelyeket egy futó programnak küldenek, hogy bizonyos viselkedést, például kilépést vagy hibakezelést indítsanak el. Ezek a folyamatok közötti kommunikáció (IPC) korlátozott formái, amelyeket általában a Unix , a Unix-szerű és más POSIX- kompatibilis operációs rendszerekben használnak.

A jel aszinkron értesítés, amelyet egy folyamatnak vagy egy adott szálnak küldenek ugyanazon a folyamaton belül, hogy értesítsék egy eseményről. A jelek gyakori felhasználása egy folyamat megszakítása, felfüggesztése, leállítása vagy megölése . A jelek az 1970 -es évek Bell Labs Unix -ból származtak, és később a POSIX szabványban kerültek meghatározásra .

Amikor egy jelet küld, az operációs rendszer megszakítja a célfolyamat normál végrehajtási folyamatát a jel továbbítása érdekében. A végrehajtás megszakítható bármely nem atomi utasítás során . Ha a folyamat korábban regisztrált egy jelkezelőt , akkor a rutin végrehajtásra kerül. Ellenkező esetben az alapértelmezett jelkezelő kerül végrehajtásra.

A beágyazott programok hasznosnak találhatják a jeleket a folyamatok közötti kommunikációban, mivel a jelek algoritmikus hatékonyságukról nevezetesek .

A jelek hasonlóak a megszakításokhoz , a különbség az, hogy a megszakításokat a CPU közvetíti és a kernel kezeli, míg a jeleket a kernel közvetíti (esetleg rendszerhívásokon keresztül), és egyes folyamatok kezelik . A rendszermag áthaladhat egy megszakítási, mint egy jel, hogy a folyamatot, ami okozta (jellemző példák SIGSEGV , SIGBUS , SIGILL és SIGFPE ).

Történelem

1. verzió A Unixnak külön rendszerhívásai voltak a megszakítások, kilépések és a gépcsapdák elfogására. 4-es verziója egyesítettük csapdák egyetlen hívás jel , és mindegyik számozott csapda kapott egy szimbolikus nevet 7-es verzió . A kill a 2 -es verzióban jelent meg , és az 5 -ös verzió tetszőleges jeleket küldhet. A Bell Labs 9. terve a jeleket jegyzetekkel helyettesítette , amelyek lehetővé teszik a rövid, tetszőleges karakterláncok küldését.

Jelek küldése

A kill (2) rendszerhívás meghatározott jelet küld egy meghatározott folyamatnak, ha az engedélyek ezt lehetővé teszik. Hasonlóképpen, a kill (1) parancs lehetővé teszi a felhasználó számára, hogy jeleket küldjön a folyamatoknak. A raise (3) könyvtári függvény elküldi a megadott jelet az aktuális folyamatnak.

Kivételek például a nullával való osztást vagy szegmentációs hiba jeleket állít elő (itt SIGFPE „lebegőpontos kivétel” és SIGSEGV „szegmentációs hiba” volt, ami mind alapértelmezés oka a core dump és program kilép).

A kernel jeleket tud generálni, hogy értesítse a folyamatokat az eseményekről. Például a SIGPIPE akkor jön létre, amikor egy folyamat ír egy csőbe, amelyet az olvasó lezárt; alapértelmezés szerint ez leállítja a folyamatot, ami kényelmes, ha shell csővezetékeket építünk .

Bizonyos billentyűkombinációk beírása egy futó folyamat vezérlőterminálján a rendszer bizonyos jeleket küld:

  • A Ctrl-C (régebbi Unix-oknál DEL) INT jelet küld ("megszakítás", SIGINT ); alapértelmezés szerint ez leállítja a folyamatot.
  • A Ctrl-Z TSTP jelet küld ("terminál leállítás", SIGTSTP ); alapértelmezés szerint ez a folyamat felfüggeszti a végrehajtást.
  • A Ctrl- \ QUIT jelet küld ( SIGQUIT ); alapértelmezés szerint ez azt eredményezi, hogy a folyamat leáll és kiüríti a magot.
  • A Ctrl-T (nem minden UNIX-on támogatott) INFO jelet küld ( SIGINFO ); alapértelmezés szerint, és ha ezt a parancs támogatja, az operációs rendszer információkat jelenít meg a futó parancsról.

Ezek az alapértelmezett billentyűkombinációk a modern operációs rendszerekkel az stty paranccsal módosíthatók .

A jelek kezelése

A jelkezelőket a jel (2) vagy a sigaction (2) rendszerhívással lehet felszerelni. Ha egy adott jelhez nincs telepítve jelkezelő, akkor az alapértelmezett kezelőt használja. Ellenkező esetben a jelet elfogják, és a jelkezelőt hívják meg. A folyamat két alapértelmezett viselkedést is megadhat, kezelő létrehozása nélkül: figyelmen kívül hagyja a jelet (SIG_IGN), és használja az alapértelmezett jelkezelőt (SIG_DFL). Két jel van, amelyet nem lehet lehallgatni és kezelni: SIGKILL és SIGSTOP .

Kockázatok

A jelkezelés sérülékeny a versenykörülményekkel szemben . Mivel a jelek aszinkronok, egy másik (akár azonos típusú) jel is továbbítható a folyamathoz a jelkezelési rutin végrehajtása során.

A sigprocmask (2) hívás használható a jelek továbbításának blokkolására és feloldására. A blokkolt jelek nem kerülnek továbbításra a folyamathoz, amíg fel nem oldják. A nem figyelmen kívül hagyható jeleket (SIGKILL és SIGSTOP) nem lehet blokkolni.

A jelek a folyamatban lévő rendszerhívás megszakítását okozhatják, és az alkalmazásra bízzák a nem átlátszó újraindítás kezelését .

A jelfeldolgozókat úgy kell írni, hogy azok ne okozzanak nemkívánatos mellékhatásokat, pl. Hibaváltozást , jelmaszk- módosítást, jelrendelet- változást és egyéb globális folyamatattribútum- változásokat. A nem ismétlődő funkciók, például a malloc vagy a printf használata a jelkezelőkben szintén nem biztonságos. Különösen a POSIX specifikáció és a Linux kézi lapjel (7) megköveteli, hogy a jelfunkcióból közvetlenül vagy közvetve meghívott összes rendszerfunkció legyen aszinkronjel-biztonságos . A jel-biztonság (7) kézikönyv felsorolja az ilyen aszinkron-jel biztonságos rendszerfunkciókat (gyakorlatilag a rendszer hív ), ellenkező esetben ez egy nem definiált viselkedés . Javasoljuk, hogy egyszerűen állítson be egy volatile sig_atomic_tváltozót egy jelkezelőben, és tesztelje máshol.

Jelkezelők ehelyett tegye a jelet egy sorba , és azonnal visszatér. A fő szál ezután "megszakítás nélkül" folytatódik, amíg jeleket nem vesz fel a sorból, például egy eseményhurokban . A "megszakítás nélküli" itt azt jelenti, hogy a blokkoló műveletek idő előtt visszatérhetnek, és a fent említettek szerint folytatni kell őket . A jeleket a fő szálon lévő sorból kell feldolgozni, és nem dolgozói csoportok által , mivel ez újra bevezeti az aszinkronitás problémáját. A sor kezelése azonban nem lehetséges aszinkronjel-biztonságos módon, csak a sig_atomic_t használatával , mivel az ilyen változókhoz csak egyetlen olvasás és írás garantáltan atomi lesz, nem pedig növekmény vagy (lekérés és csökkentés), ahogy az a egy sor. Így gyakorlatilag kezelőnként csak egy jel sorba állítható biztonságosan a sig_atomic_t segítségével, amíg fel nem dolgoztuk.

Kapcsolat hardveres kivételekkel

Egy folyamat végrehajtása hardveres kivételt eredményezhet , például, ha a folyamat megpróbál nullával osztani, vagy oldalhibát okoz .

A Unix-szerű operációs rendszerek, ez az esemény automatikusan megváltoztatja a processzor összefüggésben kezdeni végrehajtó kernel kivételkezelőt . Néhány kivétel, például oldalhiba esetén a kernel elegendő információval rendelkezik ahhoz, hogy teljes mértékben kezelje magát az eseményt, és folytathassa a folyamat végrehajtását.

Más kivételek azonban a kernel nem tud intelligens módon feldolgozni, és ehelyett el kell halasztani a kivételkezelési műveletet a hibás folyamatra. Ezt a halasztást a jelmechanizmuson keresztül érik el, ahol a kernel az aktuális kivételnek megfelelő jelet küld a folyamatnak. Például, ha egy folyamat megpróbál egész számot osztani nullával egy x86 -os CPU -n , akkor osztási hiba kivétel jön létre, és a rendszermag elküldi a SIGFPE jelet a folyamatnak.

Hasonlóképpen, ha a folyamat megkísérelné elérni a memóriacímet a virtuális címterén kívül , a kernel SIGSEGV jelzéssel értesítené a folyamatot erről a jogsértésről . A jelnevek és a kivételek közötti pontos leképezés nyilvánvalóan a CPU -tól függ, mivel a kivételek típusai eltérőek az architektúrák között.

POSIX jelek

Az alábbi lista dokumentálja a Single Unix specifikációban meghatározott jeleket . A <signal.h>fejléc fájlban minden jel makróállandóként van definiálva . A makróállandó neve "SIG" előtagból áll, amelyet a jel mnemonikus neve követ.

SIGABRT ésSIGIOT
A SIGABRT és SIGIOT jelet elküldik egy folyamatnak, hogy megszakítsák , azaz leállítsák. A jelet általában maga a folyamat kezdeményezi, amikor meghívja abort()a C Standard Library funkciót , de kívülről is elküldhető a folyamathoz, mint bármely más jel.
SIGALRM ,SIGVTALRM ésSIGPROF
A SIGALRM, SIGVTALRM és SIGPROF jeleket egy folyamat küldi, amikor az előző riasztási beállítási funkció (például setitimer) hívásakor megadott időkorlát letelik. A SIGALRM akkor kerül elküldésre, amikor a valós vagy az óra eltelik. A SIGVTALRM akkor kerül elküldésre, amikor a folyamat által használt CPU idő lejár. A SIGPROF akkor kerül elküldésre, amikor a folyamat és a rendszer által a folyamat nevében használt CPU idő eltelik.
SIGBUS
A SIGBUS jelet egy folyamat küldi, ha buszhibát okoz . A jel elküldéséhez vezető feltételek például a memóriahozzáférés helytelen beállítása vagy a nem létező fizikai cím.
SIGCHLD
A SIGCHLD jelet akkor küldik egy folyamatnak, amikor egy gyermekfolyamat leáll , megszakad vagy megszakítás után folytatódik. A jel egyik gyakori felhasználása az, hogy az operációs rendszert arra utasítja, hogy a megszűnése után tisztítsa meg a gyermekfolyamat által használt erőforrásokat, anélkül, hogy kifejezett hívást kezdeményezne a waitrendszerhívásra.
SIGCONT
A SIGCONT jel arra utasítja az operációs rendszert, hogy folytassa (indítsa újra) a SIGSTOP vagy SIGTSTP jel által korábban szüneteltetett folyamatot. Ennek a jelnek az egyik fontos felhasználási területe a Unix burkolat feladatkezelése .
SIGFPE
A SIGFPE jelet akkor küldik el egy folyamatnak, amikor kivételes (de nem feltétlenül hibás) állapotot észlelt a lebegőpontos vagy egész számtani hardver. Ez magában foglalhatja a nullával való osztást , a lebegőpontos alul- vagy túlfolyást, az egész szám túlcsordulását, az érvénytelen műveletet vagy a pontatlan számítást. A viselkedés hardvertől függően eltérő lehet.
SIGHUP
A SIGHUP jel egy folyamatba kerül, amikor a vezérlőterminál zárva van. Eredetileg úgy tervezték, hogy értesítse a folyamatot egy soros vonalcsökkenésről ( leállás ). A modern rendszerekben ez a jel általában azt jelenti, hogy a vezérlő ál- vagy virtuális terminált bezárták. Sok démon (akinek nincs vezérlőterminálja) úgy értelmezi ennek a jelnek a fogadását, mint kérést a konfigurációs fájlok újratöltésére és a naplófájlok kiöblítésére/újbóli megnyitására a kilépés helyett. A nohup egy parancs arra, hogy a parancs figyelmen kívül hagyja a jelet.
SIGILL
A SIGILL jel egy folyamatba kerül, amikor egy illegális , hibásan formázott, ismeretlen vagy kiváltságos utasítás végrehajtására tesz kísérletet .
JEL
A SIGINT jelet a vezérlőterminál küldi egy folyamatnak, amikor a felhasználó meg akarja szakítani a folyamatot. Ezt általában a Ctrl+C gomb megnyomásával kezdeményezik , de egyes rendszereken a " törlés " karakter vagy a " break " billentyű használható.
SIGKILL
A SIGKILL jelet egy folyamatba küldik, hogy az azonnal leálljon ( kill ). A SIGTERM-el és a SIGINT-el ellentétben ezt a jelet nem lehet elkapni vagy figyelmen kívül hagyni, és a fogadási folyamat semmiféle tisztítást nem végez a jel vételekor. A következő kivételek érvényesek:
  • A zombi folyamatokat nem lehet megölni, mivel már halottak, és várják, hogy a szülői folyamatok learatják őket.
  • A blokkolt állapotban lévő folyamatok nem halnak meg, amíg újra fel nem ébrednek.
  • Az init folyamat különleges: nem kap jeleket, amelyeket nem akar kezelni, és így figyelmen kívül hagyhatja a SIGKILL -t. Kivétel ez alól a szabály alól, hogy az init ptraced Linuxon.
  • Egy uninterruptibly alszik eljárás nem szüntetheti meg (és szabad erőforrásait) akkor is, ha küldött SIGKILL. Ez azon kevés esetek egyike, amikor a UNIX rendszert újra kell indítani egy ideiglenes szoftverprobléma megoldásához.
A SIGKILL -t végső megoldásként használják a folyamatok leállításakor a legtöbb rendszerleállítási eljárásban, ha önként nem lép ki a SIGTERM -re válaszul. A számítógép leállításának felgyorsítása érdekében a Mac OS X 10.6, más néven Snow Leopard elküldi a SIGKILL -t azoknak az alkalmazásoknak, amelyek "tisztának" jelölték magukat, ami gyorsabb leállási időket eredményez, vélhetően nincsenek káros hatások. A parancsnak killall -9hasonló, de veszélyes hatása van, például Linux esetén is; nem hagyja, hogy a programok a nem mentett adatokat mentsék. Más opciókkal is rendelkezik, és egyik sem használja a biztonságosabb SIGTERM jelet.
SIGPIPE
A SIGPIPE jelet egy folyamat küldi, amikor egy csőre próbál írni anélkül, hogy a másik végéhez csatlakoztatott folyamat lenne.
SIGPOLL
A SIGPOLL jel akkor kerül elküldésre, amikor egy esemény történt egy kifejezetten figyelt fájlleírón. Hatékony használata aszinkron I/O kérésekhez vezet, mivel a rendszermag lehívja a leírót a hívó helyett. Alternatívát nyújt az aktív szavazáshoz .
SIGRTMIN -SIGRTMAX
A SIGRTMIN-SIGRTMAX jeleket a felhasználó által meghatározott célokra kell használni. Ezek valós idejű jelek.
SIGQUIT
A SIGQUIT jelet küldenek a folyamatot vezérlő terminálról, ha a felhasználó kéri, hogy a folyamat kilép , és végre egy core dump .
SIGSEGV
A SIGSEGV jelet küldenek a folyamatot, amikor azt teszi érvénytelen virtuális memória hivatkozás vagy szegmentációs hiba , vagyis ha végez seg elmeállapot v iolation .
SIGSTOP
A SIGSTOP jel arra utasítja az operációs rendszert, hogy állítsa le a folyamatot a későbbi folytatáshoz.
SIGSYS
A SIGSYS jel akkor kerül elküldésre egy folyamatnak, amikor rossz argumentumot továbbít egy rendszerhívásnak . A gyakorlatban ritkán találkozunk ilyen jelzéssel, mivel az alkalmazások a könyvtárakra (pl. Libc ) támaszkodva hívják fel őket. A SIGSYS -t olyan alkalmazások fogadhatják, amelyek megsértik a korlátozásra beállított Linux Seccomp biztonsági szabályokat. A SIGSYS használható idegen rendszerhívások emulálására is, pl. Emulálja a Windows rendszerhívásait Linuxon.
SIGTERM
A SIGTERM jelet elküldik egy folyamatnak, hogy kérje annak megszüntetését . A SIGKILL jelzéssel ellentétben a folyamat elkaphatja, értelmezheti vagy figyelmen kívül hagyhatja. Ez lehetővé teszi a folyamat számára, hogy szép befejezést végezzen, felszabadítva az erőforrásokat és szükség esetén az állapotot. A SIGINT közel azonos a SIGTERM -mel.
SIGTSTP
A SIGTSTP jelet küldenek a folyamatot irányító terminál kérni, hogy megáll ( t erminal st o p ). Általában a felhasználó kezdeményezi a Ctrl+Z gombot . A SIGSTOP -tól eltérően a folyamat regisztrálhat egy jelkezelőt a jelre, vagy figyelmen kívül hagyhatja azt.
SIGTTIN ésSIGTTOU
A SIGTTIN és SIGTTOU jeleket küldenek olyan folyamat, amikor megpróbál olvasni a vagy írjon ki rendre a tty míg a háttérben . Általában ezek a jeleket csak folyamatokban a munkahelyi kontroll ; A démonok nem rendelkeznek vezérlő terminálokkal, ezért soha ne fogadják ezeket a jeleket.
SIGTRAP
A SIGTRAP jel egy folyamatba kerül, amikor kivétel (vagy csapda ) következik be: olyan feltétel, amelyről a hibakereső tájékoztatást kért - például egy adott funkció végrehajtásakor, vagy amikor egy adott változó megváltoztatja az értéket.
SIGURG
A SIGURG jelet küldenek a folyamatot, amikor egy foglalat van sürgős vagy out-of-band adatok rendelkezésre olvasni.
SIGUSR1 ésSIGUSR2
A SIGUSR1 és SIGUSR2 jeleket egy folyamatba küldi, hogy jelezze a felhasználó által meghatározott feltételeket .
SIGXCPU
A SIGXCPU jel akkor kerül elküldésre egy folyamatnak, ha az a felhasználó által beállított értéket meghaladó ideig használja fel a CPU -t. A SIGXCPU jel érkezése lehetőséget ad a fogadási folyamatnak, hogy gyorsan elmentse a köztes eredményeket, és kecsesen kilépjen, mielőtt az operációs rendszer leállítja a SIGKILL jel használatával.
SIGXFSZ
A SIGXFSZ jelet küldenek a folyamatot, amikor növekszik a fájlt , amely meghaladja a megengedett legnagyobb méretet .
SIGWINCH
A SIGWINCH jelet küldenek a folyamatot, amikor a terminál, megváltoztatja a méretét (a win dow ch ange).

Alapértelmezett művelet

Egy folyamat meghatározhatja a bejövő POSIX jelek kezelésének módját . Ha egy folyamat nem határoz meg viselkedést egy jelhez, akkor az adott jel alapértelmezett kezelőjét használja. Az alábbi táblázat felsorol néhány alapértelmezett műveletet a POSIX-kompatibilis UNIX rendszerekhez, például a FreeBSD , az OpenBSD és a Linux .

Jel Hordozható
szám
Alapértelmezett művelet Leírás
SIGABRT 6 Lezárás (magkioldás) Folyamatmegszakítási jel
SIGALRM 14 Megszüntetni Ébresztőóra
SIGBUS N/A Lezárás (magkioldás) Hozzáférés a memóriaobjektum egy nem meghatározott részéhez
SIGCHLD N/A Figyelmen kívül hagyni A gyermekfolyamat leállt, leállt vagy folytatódott
SIGCONT N/A Folytatni Folytassa a végrehajtást, ha leállt
SIGFPE 8 Lezárás (magkioldás) Hibás számtani művelet
SIGHUP 1 Megszüntetni Rakd le
SIGILL 4 Lezárás (magkioldás) Illegális utasítás
JEL 2 Megszüntetni Terminal megszakítás jel
SIGKILL 9 Megszüntetni Öld meg (nem lehet elkapni vagy figyelmen kívül hagyni)
SIGPIPE 13 Megszüntetni Írj egy csőre, hogy senki ne olvassa el
SIGPOLL N/A Megszüntetni Lefordítható esemény
SIGPROF N/A Megszüntetni A profilozási időzítő lejárt
SIGQUIT 3 Lezárás (magkioldás) A terminál kilépési jele
SIGSEGV 11 Lezárás (magkioldás) Érvénytelen memóriahivatkozás
SIGSTOP N/A Álljon meg Állítsa le a végrehajtást (nem lehet elkapni vagy figyelmen kívül hagyni)
SIGSYS N/A Lezárás (magkioldás) Rossz rendszerhívás
SIGTERM 15 Megszüntetni Lezárási jel
SIGTRAP 5 Lezárás (magkioldás) Nyomkövetési/töréspont -csapda
SIGTSTP N/A Álljon meg Terminal stop jel
SIGTTIN N/A Álljon meg Háttérfolyamat olvasási kísérlet
SIGTTOU N/A Álljon meg Háttérfolyamat, íráskísérlet
SIGUSR1 N/A Megszüntetni Felhasználó által meghatározott jel 1
SIGUSR2 N/A Megszüntetni Felhasználó által meghatározott jel 2
SIGURG N/A Figyelmen kívül hagyni A sávon kívüli adatok egy aljzaton keresztül érhetők el
SIGVTALRM N/A Megszüntetni A virtuális időzítő lejárt
SIGXCPU N/A Lezárás (magkioldás) A CPU időkorlátja túllépve
SIGXFSZ N/A Lezárás (magkioldás) A fájlméret túllépve
SIGWINCH N/A Figyelmen kívül hagyni A terminál ablak mérete megváltozott
Hordozható szám:
A legtöbb jel esetében a megfelelő jelszám megvalósítás által meghatározott. Ez az oszlop a POSIX szabványban megadott számokat sorolja fel.
A műveletek magyarázata:
Befejezés  - A folyamat rendellenes befejezése. A folyamat befejeződik az _exit () összes következményével, kivéve, hogy a várakozás () és waitpid () állapot elérhetővé tétele a megadott jel rendellenes befejezését jelzi.
Terminate (core dump)  - A folyamat rendellenes befejezése. Ezenkívül előfordulhatnak a megvalósítás által meghatározott rendellenes befejezési műveletek, például egy alapvető fájl létrehozása.
Ignore  - Figyelmen kívül hagyja a jelet.
Stop  - Állítsa le (ne fejezze be) a folyamatot.
Folytatás  - Folytassa a folyamatot, ha leállt; ellenkező esetben figyelmen kívül hagyja a jelet.

Különféle jelek

A következő jelek nincsenek megadva a POSIX specifikációban. Ezeket azonban néha különböző rendszereken használják.

SIGEMT
A SIGEMT jelet egy folyamatba küldi, amikor emulátor csapda történik.
SIGINFO
A SIGINFO jelet akkor küldik el egy folyamatnak, amikor állapot ( info ) kérés érkezik a vezérlő termináltól.
SIGPWR
A SIGPWR jelet egy folyamatba küldi, amikor a rendszer áramszünetet tapasztal .
SIGLOST
A SIGLOST jel egy folyamathoz kerül elküldésre, amikor egy fájlzár elveszik .
SIGSTKFLT
A SIGSTKFLT jelet akkor küldik egy folyamatnak, amikor a társprocesszor st ac k f au lt (azaz felugrik, ha a verem üres, vagy nyomja, ha tele van). Ezt határozza meg, de nem használja Linuxon, ahol egy x87 -es társprocesszor veremhiba SIGFPE -t generál.
SIGUNUSED
A SIGUNUSED jelet egy folyamat küldi, amikor rendszerhívás történik egy nem használt rendszerhívási számmal. A legtöbb architektúrán a SIGSYS szinonimája.
SIGCLD
A SIGCLD jel a SIGCHLD szinonimája.

Lásd még

Hivatkozások

Külső linkek