Linux E X P R E S

Facebook

Signály a procesy 2

Další část o procesech od Martina Podholy . Tentokrát přišla řeč na vlákna, řízení systému a zabíjení procesů.


Systémové procesy

Jak jsme si již řekli, po startu systém spouští procesy, které se starají o jeho řízení, těm se říká systémové. Většina dalších aplikací pak využívá jejich služeb a všechny jsou jim podřízené a podléhají jejich kontrole a řízení. Jejich kompletní seznam získáme příkazem ps -ax. V moderních systémech je jich mnoho, takže výpis je nepřehledný, proto ho sem neumístím. My si řekneme hlavně o nejzákladnějším procesu, který má PID 1 a jmenuje se INIT.

Tento proces je spuštěn při startu systému, je rodičem všech dalších procesů. Všechny další procesy spouští buď sám init, nebo jeden z jeho potomků. Je jakýmsi řídícím procesem pro celý systém.

Stará se o spoustu věcí i nepřímo spjatých s procesy, jako třeba runlevely systému. Do jiného runlevelu se dá přejít právě předáním čísla runlevelu procesu init. Ten ukončí procesy nepoužité pro nový runlevel a spustí potřebné. Používá konfigurační soubor /etc/inittab, kde je veškeré jeho nastavení. Dále jsou zde služby, jako je třeba httpd démon apache web serveru, databázové démony nebo cron, který se stará o časované spouštění (plánovač).

Struktura procesu

Proces má své PID, dále prováděný kód (běh programu - execution thread), poté jsou zde data, která program používá, proměnné, otevřené soubory, adresy deskriptorů nebo ukazatelů atd.

Nakonec jsou zde knihovny, které jsou sdíleny. Takže více procesů může používat jen jednou nahrané knihovny, ale nemusí tomu být vždy.

Spuštěný proces má 4 GB paměťového prostoru, obvykle bývá nahrán od prvních 128 MB dále, zde má pocit, že je zcela osamocen. Bližšímu pohledu dovnitř procesu se budeme věnovat v dalších dílech.

Image

Každý proces má svůj vlastní zásobník a svou vlastní sadu proměnných. Ty jsou pro něj jedinečné, v případě vláken je to však jinak, více vláken jednoho programu smí používat a "vidí" proměnné hlavního vlákna atd.

Důležitá informace je, že ačkoli zde máme tzv. preemptivní multitasking, na počítači s pouze jedním procesorem může být prováděn v jednu chvíli právě jeden proces. Tudíž současný běh více procesů je jen jakási informace o stavu procesu, který očekává práci okamžitě, jakmile mu bude přidělen čas procesoru. O tom rozhoduje jeho priorita, ale to už se dostáváme do další kapitoly.

Process scheduling

Již jsem zmínil, že v jednu chvíli je zpracováván právě jeden proces, tak proč je systém tedy víceúlohový? Čas přidělený každému programu je velmi krátký, proto to vypadá, že běží současně. Pokud je proces v běhu, znamená, že je "postupně prováděn", zpracováván.

Kdyby čekal na ukončení jiného procesu (třeba z důvodu potřeby spuštění ne současně, ale po sobě, nebo nedostatku paměti), nejednalo by se o současný běh. V podstatě multitasking znamená, že procesor "přecvakává" (tiká, chcete-li) mezi určitou množinou procesů, říkáme, že ty jsou právě zpracovávány, prováděny. Kdežto jiné procesy, které mohou být v paměti nebo swapu nahrané, čekají, až je procesor začne provádět také.

Jakým způsobem je čas procesoru přidělován, řídí jádro systému. Využívá k tomu tzv. process scheduler. Využívá jejich prioritu, podle ní posoudí, na který proces má přijít řada častěji než na jiný. Časové intervaly jsou pro všechny procesy naprosto stejné, což je již zmiňovaná další vlastnost preemptivního multitaskingu.

Určení priority procesu

Priorita neboli přednost procesu se určuje podle nice hodnoty. Základní hodnota, kterou proces může obdržet, je 10. Pak závisí na běhu programu. Těm, které běží nepřerušeně delší dobu, je přidělována nižší hodnota. Chceme-li zjistit tyto hodnoty, použijeme k příkazu ps přepínač -f.

Aby byla zajištěna rychlá odezva programů, systém sníží nice hodnotu, tím dostane program do popředí a docílí tak jeho rychlé odezvy. K dispozici máme také příkazy nice. Příkaz nice sníží hodnotu nice o 10. nice hodnota bývá často také záporná, všimněte si u top nebo ps -fa (-fx).

Vlákna

Vlákno umožňuje více samostatným segmentům systému (procesům) sdílet proměnné a vůbec data v paměti (pozor, nejedná se o sdílení paměti, to je jiná kapitola). Navenek se však jedná o více procesů a vypadají a chovají se jako procesy ve vztahu child/parent. Jediným rozdílem je, že sdílí ony řečené proměnné a program má díky nim více vláken běhu aplikace (execution threads).

Avšak jejich programování je velmi obtížné a snadno se do něj zanese řada chyb spojených s načasováním. Používá se obvykle u serverů, které potřebují spustit řadu obslužných procesů (PostgreSQL, MySQL nebo Apache).

My se jejich programováním v tomto seriálu zabývat nebudeme, jedná se opravdu o velice náročnou kapitolu a vyžaduje dost praxe s procesy a představu o tom, co děláme. Tento velmi stručný popis vlákna uvádím pro úplnost.

Signály

Jsou velmi mocným nástrojem pro řízení procesů systému. Určitě jste si už všimli "hlášky" při vypínání počítače

INIT: Sending all processes the TERM signal
INIT: Sending all processes the KILL signal

Tento výpis znamená, že proces INIT zasílá všem svým child procesům TERM signál, poté chvíli počká a zašle jim signál KILL. TERM signál "požádá" aplikaci o její ukončení a dá jí čas, aby se ukončila správným způsobem. Tento signál nezničí aplikace, které se "zasekly". Když čas vyprší, je zaslán signál KILL (ten nelze odchytit ani ignorovat) a aplikace je nadobro "zabita".

Tím jsem vám napověděl, co to signál je a že se s ním, možná nevědomky, setkáváte každý den. Teď však trochu teorie.

Signál je systémem generovaná událost, kterou používá na základě reakce na podmínku a dává tím procesu šanci provést odezvu. Používají se při chybách v programech. Vyvolává je shell nebo terminal driver nebo si je procesy posílají mezi sebou.

Signál můžeme naprogramovat (jeho zaslání), odchytit, reagovat na něj a některé můžeme ignorovat.

Signály začínají prefixem SIG (u výpisu výše je shellem odstraněn pro snažší čitelnost). Například signál SIGSEGV hlásí špatný přístup k segmentu paměti. Nejčastěji ho můžete vidět třeba při programování s knihovnou curses, umístíte-li okno mimo logickou obrazovku nebo zapíšete-li informaci do okna mimo jeho hranici a způsobíte tím posuv mimo logickou obrazovku (stdscr).

Nebo také když v programu dojde k zapeklité chybě s ukazatelem na proměnnou a zapíšete třeba na neexistující adresu, to je však málo častá chyba a dochází k ní spíše u mnohonásobné dereference. Většinu chyb odhalíte při kompilaci.

Základní signály jsou zhruba tyto:

SIGTERM         - žádost o ukončení procesu
SIGSEGV         - porušení segmentace paměti
SIGABORT        - přerušení procesu
SIGHUP          - odříznutí od terminálu (hangup)
SIGKILL         - "vražda"
SIGQUIT         - ukončení terminálové relace procesu 
SIGGINT         - přerušení terminálu
SIGGILL         - neplatná instrukce
SIGCONT         - navrácení procesu ze stavu pozastavení
SIGSTOP         - pozastavení procesu (opak SIGCONT)
SIGINT          - ukončení procesu na popředí

Signály se dají použít v našich programech, to uvidíte v pozdějších dílech. Teď si ukážeme, jak se dá procesu signál zaslat příkazem. Pokud chceme ukončit proces běžící na popředí, pošleme mu signál SIGINT, učiníme tak stiskem kláves [Ctrl+C].

Ukončení procesu na pozadí provedeme zasláním signálu pomocí příkazu kill (pozor nejedná se o SIGKILL, ačkoli tento signál také umí zaslat). Tedy kill -QUIT 1786. Obecný předpis je kill -JMENO_SIGNALU PID. Pokud chceme procesu 458 poslat signál SIGKILL, uděláme to takto: kill -KILL 458. Můžeme si vybrat libovolný signál, avšak procesy, které jste nespustili vy, nemůžete ukončit, nepodaří se vám to (pokud nejste root).

Ještě máme k dispozici alternativu, příkaz killall, který zasílá signál všem procesům, které vykonávají daný příkaz. Když chceme pozastavit všechny procesy libovolných jmen a PIDů, které provádí příkaz

cat /dev/psaux > /dev/null &

provedeme to takto:

killall -STOP cat

Diskuze (0) Nahoru