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ístty
příkaz. SIGTTIN
aSIGTTOU
jsou odeslány, když se proces na pozadí pokusí číst nebo zapisovat na svůj řídicí terminál.SIGWINCH
je odeslána jako signál, že se změnila velikost okna terminálu.SIGHUP
je 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:
SIGBUS
pro nezarovnanou přístupovou paměť;SIGSEGV
pro přístup k nezmapované stránce;SIGILL
za nelegální pokyn (špatný operační kód);SIGFPE
pro 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:
SIGALRM
upozorní, že časovač nastavený procesem vypršel. Časovače lze nastavit pomocíalarm
,setitimer
a další.SIGCHLD
oznámí procesu, že jedno z jeho dětí zemřelo.SIGPIPE
se generuje, když se proces pokusí zapsat do roury, když byl konec čtení uzavřen (myšlenkou je, že když spustítefoo | bar
abar
ukončí,foo
je 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_SETSIG
ioctl
. Mnoho systémů umožňuje volatelné události na libovolném deskriptoru souboru nastaveném pomocíO_ASYNC
fcntl
vlajka. Související signál jeSIGURG
, který upozorňuje na urgentní data na zařízení (registrovaném prostřednictvímI_SETSIG
ioctl
) nebo zásuvka.- Na některých systémech
SIGPWR
je 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
.