Někdy jsem trochu zmatený všemi signály, které může proces přijímat. Pokud tomu dobře rozumím, proces má výchozí handler (dispozice signálu ) pro každý z těchto signálů, ale může poskytnout svou vlastní obsluhu voláním sigaction() .
Zde je tedy moje otázka:co způsobuje odeslání každého ze signálů? Uvědomuji si, že můžete ručně posílat signály běžícím procesům pomocí -s parametr kill , ale jaké jsou přirozené okolnosti, za kterých jsou tyto signály vysílány? Například, kdy se SIGINT nechat poslat?
Existují také nějaká omezení ohledně toho, které signály lze zpracovat? Může dokonce SIGSEGV signály zpracovat a řízení vrátit aplikaci?
Přijatá odpověď:
Kromě procesů volajících kill(2) , některé signály posílá jádro (nebo někdy i samotný proces) za různých okolností:
- Ovladače terminálu odesílají signály odpovídající různým událostem:
- Oznámení o stisknutí kláves:
SIGINT(vraťte se prosím zpět do hlavní smyčky) na Ctrl +C ,SIGQUIT(prosím okamžitě ukončete) na Ctrl + ,SIGTSTP(prosím pozastavení) na Ctrl +Z . Klíče lze změnit pomocísttypříkaz. SIGTTINaSIGTTOUjsou odeslány, když se proces na pozadí pokusí číst nebo zapisovat na svůj řídicí terminál.SIGWINCHje odeslána jako signál, že se změnila velikost okna terminálu.SIGHUPje odeslána jako signál, že terminál zmizel (historicky proto, že váš modem měl h ung nahoru , v dnešní době obvykle proto, že jste zavřeli okno emulátoru terminálu).
- Oznámení o stisknutí kláves:
- Některé procesorové pasti mohou generovat signál. Podrobnosti jsou závislé na architektuře a systému; zde jsou typické příklady:
SIGBUSpro nezarovnanou přístupovou paměť;SIGSEGVpro přístup k nezmapované stránce;SIGILLza nelegální pokyn (špatný operační kód);SIGFPEpro instrukci s plovoucí desetinnou čárkou se špatnými argumenty (např.sqrt(-1)).
- Několik signálů oznamuje cílovému procesu, že došlo k nějaké systémové události:
SIGALRMupozorní, že časovač nastavený procesem vypršel. Časovače lze nastavit pomocíalarm,setitimera další.SIGCHLDoznámí procesu, že jedno z jeho dětí zemřelo.SIGPIPEse generuje, když se proces pokusí zapsat do roury, když byl konec čtení uzavřen (myšlenkou je, že když spustítefoo | barabarukončí,fooje zabitSIGPIPE).SIGPOLL(také nazývanéSIGIO) oznámí procesu, že došlo k položitelné události. POSIX specifikuje události s možností dotazování registrované prostřednictvímI_SETSIGioctl. Mnoho systémů umožňuje volatelné události na libovolném deskriptoru souboru nastaveném pomocíO_ASYNCfcntlvlajka. Související signál jeSIGURG, který upozorňuje na urgentní data na zařízení (registrovaném prostřednictvímI_SETSIGioctl) nebo zásuvka.- Na některých systémech
SIGPWRje odeslána všem procesům, když UPS signalizuje, že hrozí výpadek proudu.
Tyto seznamy nejsou vyčerpávající. Standardní signály jsou definovány v signal.h .
Většinu signálů může aplikace zachytit a zpracovat (nebo ignorovat). Jediné dva přenosné signály, které nelze zachytit, jsou SIGKILL (stačí zemřít) a STOP (zastavit provádění).
SIGSEGV (chyba segmentace) a jeho příbuzný SIGBUS (chyba autobusu) lze zachytit, ale je to špatný nápad, pokud opravdu nevíte, co děláte. Běžnou aplikací pro jejich zachycení je tisk trasování zásobníku nebo jiných informací o ladění. Pokročilejší aplikací je implementace nějakého druhu správy paměti v průběhu procesu nebo zachycení špatných instrukcí ve virtuálních strojích.
Nakonec mi dovolte zmínit něco, co není signál. Když stisknete Ctrl +D na začátku řádku v programu, který čte vstup z terminálu, to programu sděluje, že je dosaženo konce vstupního souboru. Toto není signál:je přenášen prostřednictvím rozhraní API pro vstup/výstup. Jako Ctrl +C a přátelé, klíč lze nakonfigurovat pomocí stty .