Signál (informatika)

Signál je v informatice jednoduchá zpráva, která se posílá procesům. Signály slouží v unixových systémech k informování procesu o výskytu události. Pomocí signálů lze meziprocesově komunikovat a manipulovat s procesy (ukončovat, pozastavovat, atd.).

Příjemcem/odesílatelem signálu může být jen proces (v Unixech může být odesílatelem i jádro operačního systému).

Jestliže proces obdrží signál, začne se ihned provádět příslušná akce, i když nebyla dokončena právě zpracovávaná funkce. Mluvíme tzv. o asynchronních signálech. Po dokončení akce pokračuje program od místa přerušení (pokud nebyl ukončen).

Dělení signálů

Signály se dělí do dvou skupin:

  1. Signály, které se posílají při chybové události
    • SIGILL (Illegal Instruction) – posílá jádro, jestliže se proces pokusí provést neplatnou, neznámou nebo privilegovanou instrukci
  2. Signály vznikající mimo proces při asynchronní události
    • SIGINT (Interrupt) posílá se procesu po stisknutí CTRL-c

Druhy akcí

Signál je jen obyčejné celé číslo. Jestliže však o nich mluvíme, odvoláváme se na ně jmény. Když proces dostane signál, zareaguje nějakou akcí, které dělíme do tří skupin:

  1. Implicitní akce – každý signál má za následek provedení nějaké implicitní akce, která je provedena, pokud proces, pro který je signál určen, nevyžaduje jinou akci
  2. Ignorování signálu – proces nemusí na signály reagovat
  3. Obsluha signálu – příchozí signál se obslouží pomocí uživatelsky definované funkce (handler). Jakmile se provede, proces pokračuje od místa, kde byl signálem přerušen.

Seznam implicitních akcí

  • exit – zrušení procesu
  • core – zrušení procesu a uložení obsahu jeho paměti do souboru core- ten se využívá pro analyzování chyb
  • ignore – ignorování signálu
  • stop – pozastavení procesu
  • continue – pokračování pozastaveného procesu

Dva signály provedou implicitní akci vždy. Je to SIGKILL (ukončí proces) a SIGSTOP (pozastaví proces).

Posílání signálů

Proces s UID (User ID) rovným nule může poslat signál libovolnému procesu. Proces, který má UID různé od nuly, může v Linuxu poslat signál těm procesům, které mají stejné reálné nebo saved UID jako má on reálné UID. Ve FreeBSD se musí UID procesů shodovat.

Signál pošleme z příkazového řádku (shellu) příkazem:

# kill [-s signal] PID

PID je číslo procesu (Process ID). Příkaz se jmenuje kill (česky zabít), protože původně vznikl kvůli ukončování procesů. Pokud není uvedeno číslo signálu, posílá se implicitně signál TERM.

Programově se signál posílá voláním funkce:

int kill(pid_t pid, int sig);  // (viz man 2 kill)

Funkce pošle signál sig jednomu nebo skupině procesů (podle hodnoty PID). Je-li sig==O, tak se pouze zjistí, má-li proces oprávnění poslat signál. Jakým procesům se signál pošle, záleží jen pid:

  • pid > 0 – pošle se procesu s pid
  • pid == 0 – pošle se procesům ve stejné skupině
  • pid == -1 – pošle se všem procesům kromě systémových
  • pid < -1 – pošle se procesům ve skupině s číslem -pid

Obsluha signálů

Jak je psáno výše, jsou signály asynchronní. Při obsluze tedy není zřejmé, v jakém se proces nachází stavu. Kvůli tomu by se měly v handlerech provádět jen bezpečné funkce (man sigaction). Výkon handleru pro obsluhu může být přerušen příchodem jiného signálu. Handler by měl vykonávat co nejméně operací, proto často jen zaznamená, že přišel signál. Program mimo handler periodicky kontroluje, zda přišel signál a eventuálně provádí požadovanou akci.

K nastavení obsluhy signálu slouží funkce:

int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);

Funkce nastaví obsluhu signálu sig podle act a do oldact uloží předchozí nastavení obsluhy. Struktura sigaction je definována takto:

struct sigaction
 {
  void (*sa_handler)(int);
  void (*sa_sigaction)(int, siginfo_t *, void *);
  sigset_t sa_mask;
  int sa_flags;
  void (*sa_restorer)(void);
 }

kde void (*sa_handler)(int) specifikuje akci svázanou se signálem – buď adresa handleru nebo SIG_DFL (výchozí akce), SIG_IGN (ignorování signálu). Díky sigset_t sa_mask můžeme nastavit masku signálu, které budou blokovány v handleru. int sa_flags přetvářejí chování handleru (např. SA_RESTART – restartovat přerušená systémová volání, SA_ONESHOT – po prvním obsloužení nastavit obsluhu na výchozí akci). Podrobnější popis lze najít v manuálových stránkách, viz man sigaction.

Někdy je těžké zajistit, aby program správně obsloužil signál, který může kdykoliv přijít a přerušit běh programu. Jestliže se tomuto chceme vyhnout, použijeme mechanismus blokování signálu. Blokované signály jsou ignorovány až do jejich odblokování, poté jsou procesu doručeny. Na rozdíl od ignorovaných, které jádro zahazuje a tak nejsou nikdy doručeny. K nastavování blokovaných signálů se používá funkce:

int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);

Funkce nastaví masku blokovaných signálů a vrátí starou masku. Chování se nastaví hodnotou how – SIG_BLOCK (blokují se stejné signály jako doposud a navíc ty definované argumentem set), SIG_UNBLOCK (signály v set jsou vyjmuty z blokovaných), SIG_SETMASK (blokovány signály definované v set).

Maska signálu se nastavuje funkcemi:

  • int sigemptyset(sigset_t *set) – inicializuje množinu signálů danou set na prázdnou
  • int sigfillset(sigset_t *set) – inicializuje množinu signálů danou set na všechny definované signály
  • int sigaddset(sigset_t *set, int signum) – přidá do množiny signálu signál signum
  • int sigdelset(sigset_t *set, int signum) – vymaže z množiny signálů signál signum
  • int sigismember(const sigset_t *set, int signum) – zjistí, zda je signál v dané množině signálů

Pro získání signálů, které čekají na odblokování, se používá funkce int sigpending(sigset_t *set);. Pokud je potřeba proces pozastavit, dokud nepřijde nějaký signál, využívá se funkce int pause() nebo funkce int sigsuspend(const sigset_t *sigmask), která dále mění masku blokovaných signálů danou pointrem *sigmask.

Seznam signálů

Rodina standardů Single UNIX Specification definuje následující signály v hlavičkovém souboru signal.h:

Název signálu Kód signálu Popis
SIGABRT 6 Proces přerušen
SIGALRM 14 Vygenerován signál alarm
SIGBUS 10 Chyba sběrnice: „přístup do nedefinované oblasti paměti“
SIGCHLD 18 Potomek ukončen, pozastaven nebo znovu pokračuje*
SIGCONT 25 Pokračování, je-li pozastaven
SIGFPE 8 Chyba při zpracování čísla v plovoucí řádové čárce: „chybná aritmetická operace“
SIGHUP 1 Signál zavěšení
SIGILL 4 Neplatná strojová instrukce
SIGINT 2 Přerušení
SIGKILL 9 Kill (okamžité ukončení)
SIGPIPE 13 Zápis do roury, ze které nikdo nečte
SIGQUIT 3 Ukončit a vygenerovat core
SIGSEGV 11 Porušení ochrany paměti (segmentation fault, segmentation violation)
SIGSTOP 23 Dočasné pozastavení procesu
SIGTERM 15 Ukončení (žádost o ukončení)
SIGTSTP 23 Ukončující stop signál
SIGTTIN 26 Proces na pozadí se pokouší číst z TTY ("vstup")
SIGTTOU 27 Proces na pozadí se pokouší zapisovat na TTY ("výstup")
SIGUSR1 16 Uživatelsky definovaný 1
SIGUSR2 17 Uživatelsky definovaný 2
SIGPOLL 22 Událost pro pooling
SIGPROF 29 Expirace profilovacího časovače
SIGSYS 12 Neplatné systémové volání
SIGTRAP 5 Krokování nebo bod přerušení (trap, vnitřní přerušení)
SIGURG 21 Na soketu jsou připravena urgentní data
SIGVTALRM 28 Signalizace od časovače virtuálního času: "vypršel virtuální časovač"
SIGXCPU 30 Překročen limit času CPU
SIGXFSZ 31 Překročen limit velikosti souboru

Poznámka: Hvězdička označuje rozšíření X/Open System Interfaces (XSI). Popis v uvozovkách přidán podle SUS.[1]

Reference

  1. http://www.opengroup.org/onlinepubs/007904975 – Single UNIX Specification

Externí odkazy

This article is issued from Wikipedia. The text is licensed under Creative Commons - Attribution - Sharealike. Additional terms may apply for the media files.