Přeskočit na obsah

Signál (informatika)

Z Wikipedie, otevřené encyklopedie

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ádrooperač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ů

[editovat | editovat zdroj]

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í

[editovat | editovat zdroj]

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í

[editovat | editovat zdroj]
  • 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ů

[editovat | editovat zdroj]

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ů

[editovat | editovat zdroj]

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ů

[editovat | editovat zdroj]

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

Název signálu Kód signálu Popis
SIGABRT6 Ukončení procesu
SIGALRM14 Vygenerován signál alarm
SIGBUS10 Chyba sběrnice: „přístup do nedefinované oblasti paměti“
SIGCHLD18 Potomek ukončen, pozastaven nebo znovu pokračuje*
SIGCONT25 Pokračování, je-li pozastaven
SIGFPE8 Chyba při zpracování čísla v plovoucí řádové čárce: „chybná aritmetická operace“
SIGHUP1 Signál zavěšení
SIGILL4 Neplatná strojová instrukce
SIGINT2 Přerušení
SIGKILL9 Kill (okamžité ukončení)
SIGPIPE13 Zápis do roury, ze které nikdo nečte
SIGQUIT3 Ukončit a vygenerovat core
SIGSEGV11 Porušení ochrany paměti (segmentation fault, segmentation violation)
SIGSTOP23 Dočasné pozastavení procesu
SIGTERM15 Ukončení (žádost o ukončení)
SIGTSTP23 Ukončující stop signál
SIGTTIN26 Proces na pozadí se pokouší číst z TTY ("vstup")
SIGTTOU27 Proces na pozadí se pokouší zapisovat na TTY ("výstup")
SIGUSR116 Uživatelsky definovaný 1
SIGUSR217 Uživatelsky definovaný 2
SIGPOLL22 Událost pro polling
SIGPROF29 Expirace profilovacího časovače
SIGSYS12 Neplatné systémové volání
SIGTRAP5 Krokování nebo bod přerušení (trap, vnitřní přerušení)
SIGURG21 Na soketu jsou připravena urgentní data
SIGVTALRM28 Signalizace od časovače virtuálního času: "vypršel virtuální časovač"
SIGXCPU30 Překročen limit času CPU
SIGXFSZ31 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]

Externí odkazy

[editovat | editovat zdroj]
close