Signál (IPC) - Signal (IPC)
Signály jsou standardizované zprávy odesílané do spuštěného programu, aby spustily specifické chování, například ukončení nebo zpracování chyb. Jedná se o omezenou formu meziprocesové komunikace (IPC), která se obvykle používá v operačních systémech Unix , Unix a dalších kompatibilních s POSIX .
Signál je asynchronní oznámení odeslané do procesu nebo do určitého vlákna v rámci stejného procesu, které ho upozorní na událost. Běžné použití signálů jsou přerušit, pozastavit, ukončit nebo zabít proces. Signály vznikly v Unixu společnosti Bell Labs v sedmdesátých letech a později byly specifikovány ve standardu POSIX .
Když je odeslán signál, operační systém přeruší normální tok provedení cílového procesu, aby signál doručil. Provádění může být přerušeno během jakékoli neatomové instrukce . Pokud proces dříve zaregistroval obslužný program signálu , provede se tato rutina. V opačném případě se provede výchozí obsluha signálu.
Vestavěné programy mohou najít signály užitečné pro meziprocesovou komunikaci, protože signály jsou pozoruhodné svou algoritmickou účinností .
Signály jsou podobné přerušením , rozdíl je v tom, že přerušení jsou zprostředkována CPU a zpracovávána jádrem, zatímco signály jsou zprostředkovány jádrem (možná prostřednictvím systémových volání) a zpracovávány jednotlivými procesy . Jádro může předat přerušení jako signál procesu, který jej způsobil (typickými příklady jsou SIGSEGV , SIGBUS , SIGILL a SIGFPE ).
Dějiny
Verze 1 Unix měla samostatná systémová volání k zachycení přerušení, ukončení a zachycení stroje. Verze 4 spojila všechny pasti do jednoho hovoru, signálu a každá očíslovaná past dostala ve verzi 7 symbolické jméno . kill se objevil ve verzi 2 a ve verzi 5 mohl vysílat libovolné signály. Plán 9 od Bell Labs nahradil signály poznámkami , které umožňují odesílání krátkých, libovolných řetězců.
Odesílání signálů
Kill (2) Systémové volání vyšle určený signál na konkrétní proces, je-li oprávnění povolit. Podobně příkaz kill (1) umožňuje uživateli posílat signály do procesů. Funkce knihovny raise (3) posílá zadaný signál aktuálnímu procesu.
Výjimky, jako je dělení nulou nebo narušení segmentace, budou generovat signály (zde SIGFPE „výjimka s pohyblivou řádovou čárkou“ a SIGSEGV „narušení segmentace“, které ve výchozím nastavení způsobují jádrový výpis a ukončení programu).
Jádro může generovat signály k upozornění procesů na události. Například SIGPIPE bude generováno, když proces zapisuje do kanálu, který byl zavřen čtečkou; ve výchozím nastavení to způsobí ukončení procesu, což je výhodné při konstrukci shell kanálů .
Zadání určitých kombinací kláves na řídicí terminál běžícího procesu způsobí, že mu systém pošle určité signály:
- Ctrl-C (ve starších Unixech DEL) vysílá signál INT („přerušení“, SIGINT ); ve výchozím nastavení to způsobí ukončení procesu.
- Ctrl-Z vysílá signál TSTP („koncová zastávka“, SIGTSTP ); ve výchozím nastavení to způsobí, že proces pozastaví provádění.
- Ctrl- \ odešle QUIT signál ( SIGQUIT ); ve výchozím nastavení to způsobí ukončení procesu a vypsání jádra.
- Ctrl-T (není podporováno ve všech UNIXech) odesílá INFO signál ( SIGINFO ); ve výchozím nastavení, a pokud to příkaz podporuje, způsobí to, že operační systém zobrazí informace o spuštěném příkazu.
Tyto výchozí kombinace kláves s moderními operačními systémy lze změnit pomocí příkazu stty .
Zpracování signálů
Manipulátory signálu lze nainstalovat pomocí systémového volání signal (2) nebo sigaction (2) . Pokud není pro určitý signál nainstalován obslužný program signálu, použije se výchozí obslužný program. Jinak je signál zachycen a je vyvolán obslužný program signálu. Proces může také určit dvě výchozí chování bez vytvoření obslužné rutiny: ignorujte signál (SIG_IGN) a použijte výchozí obslužný program signálu (SIG_DFL). Existují dva signály, které nelze zachytit a zpracovat: SIGKILL a SIGSTOP .
Rizika
Zpracování signálu je citlivé na závodní podmínky . Protože jsou signály asynchronní, může být do procesu během provádění rutiny zpracování signálu dodán další signál (dokonce stejného typu).
Sigprocmask (2) volání může být použit k zablokování a odblokování dodávání signálů. Blokované signály nejsou do procesu doručovány, dokud nejsou odblokovány. Signály, které nelze ignorovat (SIGKILL a SIGSTOP), nelze blokovat.
Signály mohou způsobit přerušení probíhajícího systémového volání a ponechat aplikaci na správě netransparentního restartu .
Obslužné rutiny signálu by měly být psány způsobem, který nevede k žádným nežádoucím vedlejším účinkům, např. Ke změně chyb, změně masky signálu, změně dispozice signálu a dalším globálním změnám atributů procesu . Nebezpečné není ani používání nereentrantních funkcí, např. Malloc nebo printf , uvnitř obsluh signálů. Specifikace POSIX a signál manuálové stránky Linuxu (7) zejména vyžadují, aby všechny systémové funkce přímo nebo nepřímo volané ze signální funkce byly bezpečné pro asynchronní signál . Signálu bezpečnostní (7) man stránka obsahuje seznam organizací, jako asynchronní signálem funkce bezpečný systém (prakticky systémových volání ), v opačném případě se jedná o nedefinované chování . Doporučuje se jednoduše nastavit nějakou volatile sig_atomic_t
proměnnou v obsluze signálu a otestovat ji jinde.
Obsluha signálu může místo toho umístit signál do fronty a okamžitě se vrátit. Hlavní vlákno pak bude pokračovat „nepřerušeně“, dokud nebudou signály odebírány z fronty, například ve smyčce událostí . „Nepřerušený“ zde znamená, že operace, které blokují, se mohou předčasně vrátit a musí být obnoveny , jak je uvedeno výše. Signály by měly být zpracovávány z fronty v hlavním vlákně, a nikoli pracovními fondy , protože to znovu zavádí problém asynchronicity. Správa fronty však není možná bezpečným způsobem asynchronního signálu pouze se sig_atomic_t , protože pouze jednotlivá čtení a zápisy do těchto proměnných jsou zaručeny atomové, nikoli přírůstky nebo (načítání a) dekódování, jak by bylo požadováno pro fronta. Ve skutečnosti lze tedy pouze jeden signál na handler bezpečně zařadit do fronty pomocí sig_atomic_t, dokud nebude zpracován.
Vztah s hardwarovými výjimkami
Provádění procesu může mít za následek generování hardwarové výjimky , například pokud se proces pokusí dělit nulou nebo dojde k chybě stránky .
V operačních systémech podobných Unixu tato událost automaticky změní kontext procesoru a spustí se zpracování obslužné rutiny výjimky jádra . V případě některých výjimek, jako je například chyba stránky , má jádro dostatečné informace, aby plně zvládlo samotnou událost a obnovilo provádění procesu.
Jiné výjimky však jádro nemůže zpracovávat inteligentně a místo toho musí operaci zpracování výjimek odložit na chybující proces. Tohoto odložení je dosaženo prostřednictvím signálního mechanismu, kde jádro vysílá do procesu signál odpovídající aktuální výjimce. Pokud by se například proces pokusil o celočíselné dělení nulou na CPU x86 , vygenerovala by se výjimka chyby dělení a jádro by do procesu poslalo signál SIGFPE .
Podobně, pokud by se proces pokusil získat přístup k adrese paměti mimo svůj virtuální adresní prostor , jádro by proces upozornilo na toto narušení signálem SIGSEGV . Přesné mapování mezi názvy signálů a výjimkami je samozřejmě závislé na CPU, protože typy výjimek se mezi architekturami liší.
Signály POSIX
Níže uvedený seznam dokumentuje signály uvedené ve specifikaci Single Unix . Všechny signály jsou v souboru <signal.h>
záhlaví definovány jako makro konstanty . Název makro konstanty se skládá z předpony „SIG“ následované mnemotechnickým názvem signálu.
- SIGABRT aSIGIOT
- Signál SIGABRT a SIGIOT je odeslán do procesu, aby mu řekl, že má přerušit , tj. Ukončit . Signál je obvykle iniciován samotným procesem, když volá
abort()
funkci standardní knihovny C , ale může být odeslán do procesu zvenčí jako jakýkoli jiný signál. - SIGALRM ,SIGVTALRM aSIGPROF
- Signál SIGALRM, SIGVTALRM a SIGPROF je odeslán do procesu, když uplyne časový limit specifikovaný ve volání na předchozí funkci nastavení alarmu (například
setitimer
). SIGALRM je odeslán po uplynutí reálného nebo hodinového času. SIGVTALRM je odeslán, když vyprší čas CPU použitý procesem. SIGPROF se odešle, když uplyne čas procesoru používaný procesem a systémem jménem procesu. - SIGBUS
- SIGBUS signál je poslán do procesu, kdy to způsobuje chyby sběrnice . Podmínky, které vedou k odesílání signálu, jsou například nesprávné zarovnání přístupu do paměti nebo neexistující fyzická adresa.
- SIGCHLD
- Signál SIGCHLD je odeslán do procesu, když podřízený proces skončí , je přerušen nebo se po přerušení obnoví. Jedním z běžných použití signálu je dát operačnímu systému pokyn vyčistit prostředky používané podřízeným procesem po jeho ukončení bez výslovného volání
wait
systémového volání. - SIGCONT
- Signál SIGCONT dává operačnímu systému pokyn, aby pokračoval (restartoval) proces dříve pozastavený signálem SIGSTOP nebo SIGTSTP. Jedním z důležitých použití tohoto signálu je řízení úloh v prostředí Unix .
- SIGFPE
- Signál SIGFPE je odeslán do procesu, pokud byla v hardwaru s plovoucí desetinnou čárkou nebo celočíselným aritmetickým hardwarem detekována výjimečná (ale ne nutně chybná) podmínka. To může zahrnovat dělení nulou , přetečení s plovoucí desetinnou čárkou nebo přetečení, přetečení celého čísla, neplatnou operaci nebo nepřesný výpočet. Chování se může lišit v závislosti na hardwaru.
- PŘIPOJENÍ
- Signál SIGHUP je odeslán do procesu, když je jeho ovládací terminál zavřený. Původně byl navržen tak, aby upozornil na proces poklesu sériové linky ( zavěšení ). V moderních systémech tento signál obvykle znamená, že řídicí pseudo nebo virtuální terminál byl uzavřen. Mnoho démonů (kteří nemají žádný řídící terminál) interpretuje příjem tohoto signálu jako požadavek na opětovné načtení konfiguračních souborů a vyprázdnění/opětovné otevření souborů protokolu namísto ukončení. nohup je příkaz, který zajistí, aby příkaz ignoroval signál.
- SIGILL
- Signál SIGILL je odeslán do procesu, když se pokusí provést nezákonnou , nesprávně formátovanou, neznámou nebo privilegovanou instrukci .
- SIGINT
- Signál SIGINT je odeslán do procesu jeho řídícím terminálem, když si uživatel přeje proces přerušit . Obvykle se to spouští stisknutím Ctrl+C , ale v některých systémech lze použít znak „ odstranit “ nebo „ konec “.
- SIGKILL
- Signál SIGKILL je odeslán do procesu, aby způsobil jeho okamžité ukončení ( zabití ). Na rozdíl od SIGTERM a SIGINT nelze tento signál zachytit ani ignorovat a přijímací proces nemůže po přijetí tohoto signálu provést žádné vyčištění. Platí následující výjimky:
- Zombie procesy nelze zabít, protože jsou již mrtvé a čekají, až je jejich nadřazené procesy sklidí.
- Procesy, které jsou v zablokovaném stavu, nezemřou, dokud se znovu neprobudí.
- Proces init je speciální: Nedostává signály, které nechce zpracovat, a proto může ignorovat SIGKILL. Výjimkou z tohoto pravidla je, když je init ptraced na Linuxu.
- Proces nepřerušitelného spánku nemusí být ukončen (a uvolnit jeho zdroje), i když byl odeslán SIGKILL. Toto je jeden z mála případů, kdy může být nutné restartovat systém UNIX, aby se vyřešil dočasný problém se softwarem.
- SIGKILL se používá jako poslední možnost při ukončování procesů ve většině procedurách vypnutí systému, pokud v reakci na SIGTERM nedojde k dobrovolnému ukončení. Aby se urychlil postup vypínání počítače, Mac OS X 10.6, neboli Snow Leopard , odešle SIGKILL do aplikací, které se označily jako „čisté“, což má za následek rychlejší časy vypínání s pravděpodobně bez škodlivých účinků. Příkaz
killall -9
má podobný, i když nebezpečný účinek, když je proveden např. V Linuxu; neumožňuje programům ukládat neuložená data. Má další možnosti a bez použití bezpečnějšího signálu SIGTERM. - SIGPIPE
- Signál SIGPIPE je odeslán do procesu, když se pokouší zapsat do kanálu bez procesu připojeného k druhému konci.
- SIGPOLL
- Signál SIGPOLL je odeslán, když došlo k události na explicitně sledovaném deskriptoru souboru. Efektivní použití vede k vytváření asynchronních požadavků I/O, protože jádro bude dotazovat deskriptor místo volajícího. Poskytuje alternativu k aktivnímu hlasování .
- PŘIHLASTE se doSIGRTMAX
- Signály SIGRTMIN až SIGRTMAX jsou určeny k použití pro účely definované uživatelem. Jsou to signály v reálném čase .
- SIGQUIT
- Signál SIGQUIT je odeslán do procesu jeho řídícím terminálem, když uživatel požaduje, aby proces skončil a provedl jádrový výpis .
- SIGSEGV
- SIGSEGV signál je poslán do procesu, kdy to dělá neplatný odkaz virtuální paměť, nebo segmentace poruch , tedy když provádí seg mentace v iolation .
- SIGSTOP
- Signál SIGSTOP instruuje operační systém, aby zastavil proces pro pozdější obnovení.
- SIGSYS
- Signál SIGSYS je odeslán do procesu, když předá špatný argument systémovému volání . V praxi se s tímto druhem signálu setkáváme jen zřídka, protože aplikace se při volání spoléhají na knihovny (např. Libc ). SIGSYS mohou přijímat aplikace porušující bezpečnostní pravidla Linux Seccomp nakonfigurovaná tak, aby je omezovala. SIGSYS lze také použít k emulaci cizích systémových volání, např. Emulace systémových volání Windows na Linuxu.
- SIGTERM
- Signál SIGTERM je odeslán do procesu, aby požádal o jeho ukončení . Na rozdíl od signálu SIGKILL může být procesem zachycen a interpretován nebo ignorován. To umožňuje, aby proces provedl pěkné ukončení, uvolnění zdrojů a uložení stavu, je -li to vhodné. SIGINT je téměř identický s SIGTERM.
- SIGTSTP
- SIGTSTP signál je poslán do procesu její ovládající terminálem jej požádat o doraz ( t erminal st o p ). Obvykle jej spouští uživatel stisknutím tlačítka Ctrl+Z . Na rozdíl od SIGSTOP může proces zaregistrovat zpracovatel signálu pro signál nebo jej ignorovat.
- SIGTTIN aSIGTTOU
- Tyto SIGTTIN a SIGTTOU signály jsou odesílány do procesu, když se pokusí přečíst v či psát ven , respektive od tty , zatímco v pozadí . Tyto signály jsou obvykle přijímány pouze procesy pod kontrolou úlohy ; démoni nemají ovládací terminály, a proto by nikdy neměli přijímat tyto signály.
- SIGTRAP
- Signál SIGTRAP je odeslán do procesu, když dojde k výjimce (nebo pasti ): podmínka, o kterou debugger požádal, aby byl informován - například když je spuštěna konkrétní funkce nebo když konkrétní proměnná změní hodnotu.
- SIGURG
- Signál SIGURG je odeslán do procesu, když má zásuvka k dispozici naléhavá nebo mimopásmová data ke čtení.
- SIGUSR1 aSIGUSR2
- Signály SIGUSR1 a SIGUSR2 jsou odesílány do procesu, který indikuje uživatelem definované podmínky .
- SIGXCPU
- Signál SIGXCPU je odeslán do procesu, když vyčerpal CPU na dobu, která překračuje určitou předem stanovenou uživatelem nastavitelnou hodnotu. Příchod signálu SIGXCPU poskytuje přijímacímu procesu šanci rychle uložit všechny mezivýsledky a elegantně ukončit, než jej operační systém ukončí pomocí signálu SIGKILL.
- SIGXFSZ
- Signál SIGXFSZ je odeslán do procesu, když roste soubor, který překračuje maximální povolenou velikost .
- SIGWINCH
- Signál SIGWINCH je odeslán do procesu, když jeho ovládací terminál změní svou velikost ( výhra dow ch ange).
Výchozí akce
Proces může definovat, jak zacházet s příchozími signály POSIX . Pokud proces nedefinuje chování pro signál, použije se výchozí obsluha pro tento signál. Níže uvedená tabulka uvádí některé výchozí akce pro systémy UNIX kompatibilní s POSIX, jako jsou FreeBSD , OpenBSD a Linux .
Signál | Přenosné číslo |
Výchozí akce | Popis |
---|---|---|---|
SIGABRT | 6 | Ukončit (core dump) | Zpracovat signál přerušení |
SIGALRM | 14 | Vypovědět | Budík |
SIGBUS | N/A | Ukončit (core dump) | Přístup k nedefinované části paměťového objektu |
SIGCHLD | N/A | Ignorovat | Podřízený proces byl ukončen, zastaven nebo pokračoval |
SIGCONT | N/A | Pokračovat | Pokud je zastaveno, pokračujte v provádění |
SIGFPE | 8 | Ukončit (core dump) | Chybná aritmetická operace |
PŘIPOJENÍ | 1 | Vypovědět | Zavěsit |
SIGILL | 4 | Ukončit (core dump) | Nelegální instrukce |
SIGINT | 2 | Vypovědět | Signál přerušení terminálu |
SIGKILL | 9 | Vypovědět | Zabít (nelze chytit ani ignorovat) |
SIGPIPE | 13 | Vypovědět | Pište na dýmku, aby ji nikdo nečetl |
SIGPOLL | N/A | Vypovědět | Pollable event |
SIGPROF | N/A | Vypovědět | Profilovací časovač vypršel |
SIGQUIT | 3 | Ukončit (core dump) | Koncový signál ukončení |
SIGSEGV | 11 | Ukončit (core dump) | Neplatný odkaz na paměť |
SIGSTOP | N/A | Stop | Zastavit spouštění (nelze chytit ani ignorovat) |
SIGSYS | N/A | Ukončit (core dump) | Špatné systémové volání |
SIGTERM | 15 | Vypovědět | Ukončovací signál |
SIGTRAP | 5 | Ukončit (core dump) | Trasovací/zarážkový past |
SIGTSTP | N/A | Stop | Koncový signál zastavení |
SIGTTIN | N/A | Stop | Proces na pozadí při pokusu o čtení |
SIGTTOU | N/A | Stop | Proces na pozadí při pokusu o zápis |
SIGUSR1 | N/A | Vypovědět | Uživatelsky definovaný signál 1 |
SIGUSR2 | N/A | Vypovědět | Uživatelsky definovaný signál 2 |
SIGURG | N/A | Ignorovat | Data mimo pásmo jsou k dispozici na soketu |
SIGVTALRM | N/A | Vypovědět | Platnost virtuálního časovače vypršela |
SIGXCPU | N/A | Ukončit (core dump) | Překročen časový limit CPU |
SIGXFSZ | N/A | Ukončit (core dump) | Překročen limit velikosti souboru |
SIGWINCH | N/A | Ignorovat | Velikost okna terminálu se změnila |
- Přenosné číslo:
- Pro většinu signálů je odpovídající číslo signálu definováno implementací. Tento sloupec uvádí čísla uvedená ve standardu POSIX.
- Vysvětlené akce:
- Ukončit - Abnormální ukončení procesu. Proces je ukončen se všemi důsledky _exit () kromě toho, že stav zpřístupněný pro wait () a waitpid () označuje abnormální ukončení zadaným signálem.
- Ukončit (core dump) - Abnormální ukončení procesu. Kromě toho může dojít k implementaci abnormálních akcí ukončení, jako je vytvoření základního souboru.
- Ignorovat - signál bude ignorován.
- Zastavit - zastaví (nikoli ukončí) proces.
- Pokračovat - Pokud je proces zastaven, bude pokračovat; v opačném případě signál ignorujte.
Různé signály
Následující signály nejsou specifikovány ve specifikaci POSIX . Někdy se však používají v různých systémech.
- SIGEMT
- Signál SIGEMT je odeslán do procesu, když dojde k zachycení emulátoru .
- SIGINFO
- Signál SIGINFO je odeslán do procesu, když je z řídicího terminálu přijat požadavek na stav ( info ).
- SIGPWR
- Signál SIGPWR je odeslán do procesu, když v systému dojde k výpadku napájení .
- SIGLOST
- Signál SIGLOST je odeslán do procesu při ztrátě zámku souboru .
- SIGSTKFLT
- Signál SIGSTKFLT je odeslán do procesu, když koprocesor zažije st ac k f au lt (tj. Vyskočí, když je zásobník prázdný, nebo tlačí, když je plný). To je definováno, které však nebyly využity na Linuxu, kde X87 bude koprocesor stohu chyba generovat SIGFPE místo.
- PODPISOVÁNO
- Signál SIGUNUSED je odeslán do procesu při uskutečnění systémového volání s nepoužívaným číslem systémového volání. Je synonymem pro SIGSYS ve většině architektur.
- SIGCLD
- Signál SIGCLD je synonymem pro SIGCHLD.
Viz také
Reference
- Stevens, W. Richard (1992). Pokročilé programování v prostředí UNIX® . Reading, Massachusetts: Addison Wesley. ISBN 0-201-56317-7.
- „Specifikace otevřené skupiny, vydání 7, vydání 2013“ . Otevřená skupina . Citováno 19. června 2015 .
externí odkazy
- Tabulka signálů Unix, Ali Alanjawi, University of Pittsburgh
- Stránka Man7.org Signal Man
- Úvod do programování signálů Unix Úvod do programování signálů Unix na stroji Wayback (archivováno 26. září 2013)
- Další úvod do programování signálů Unix (příspěvek na blogu, 2009)
- UNIX a spolehlivé signály POSIX od Barise Simska
- Manipulátory signálu Henning Brauer