UNIX 12. Komunikace mezi procesy Obsah: meziprocesová komunikace soubor, sdílená paměť mapování souborů do paměti signály, zasílání zpráv roura, pojmenovaná roura, IPC soket zamykání souborů, souborové zámky © Milan Keršláger http://www.pslib.cz/ke/slajdy 30. 4. 2014 http://creativecommons.org/licenses/by-nc-nd/3.0/
Účely komunikace Inter-Process Communication (IPC) multiprogramování úloha je rozdělena na více samostatných úloh, aby mohly být zpracovávány odděleně je nutné zajistit synchronizaci, signalizaci a výměnu dat clustery výpočty probíhají na oddělených počítačích je nutné zajistit synchronizaci, signalizaci a výměnu dat při využití počítačové sítě vzniká problém souběhu problém současného zápisu více procesů do stejných dat
Souběh dva nebo více procesů modifikuje stejná data pokud by procesy byly spuštěny samostatně, k problému by nedošlo vznikají mysteriózní chyby ohrožená data mohou být uložena různě: data operačního systému: paměť jádra OS uživatelská data: soubor, sdílená paměť thready: z principu mají sdílenou paměť
Souběh – ze života sekretářka přidává všem zaměstnancům 100 Kč její program načte sdílená data sekretářka přičte 100 Kč data jsou uložena do sdíleného úložiště šéf se rozhoduje o přidělení prémie 500 Kč sekretářka načte další, ale odejde udělat kafe šéf načte stejná data, přičte 500 a data uloží sekretářka přijde, přičte 100 k původní částce sekretářka přepíše výsledek, 500 Kč se ztratí
Souběh – v počítači vytváření souborů soubor musí mít v adresáři unikátní jméno nové nejprve testujeme, pak teprve vytváříme může dojít k přerušení mezi testem a vytvořením nutnost atomické operace (typicky v jádru OS) přístup do SQL databáze aktualizace několika položek → nekonzistence dat ne vše lze vyřešit jako jedinou SQL instrukci používá se zamykání (souboru, semafory apod.) vzniká však nový problém „uváznutí“
Atomická operace proběhne jako jeden celek operaci nelze přerušit výsledek (všechny výsledky) se projeví najednou nejlépe jedna strojová instrukce delší (složitější) operace nejsou atomické atomicitu je možné zajistit jinými prostředky zákaz přerušení, instrukce TSL, semafory tj. (zdánlivě) atomický sled více strojových instrukcí (kódu) jeden CPU: operace je pak zdánlivě atomická víceprocesorový systém zdánlivá atomicita operace problém neřeší řešení: budeme chránit (zamykat) data
Pojmy pro popis souběhu kritická oblast data sdílena několika procesy (thready) kritická sekce nejmenší část programu pracující s kritickou oblastí může do ní vstoupit maximálně jeden proces při řízení přístupu do kritické sekce tři problémy: zajištění výhradního přístupu vývoj omezené čekání musí být provedena jako jeden celek
Zajištění výhradního přístupu atomická operace lze využít jen výjimečně zákaz přerušení používá se běžně v jádře OS instrukce TSL neodstraňuje problém aktivního čekání semafory univerzálnější, ale složitější implementace RCU
Atomická operace tj. operace proběhne jako jeden celek operaci nelze přerušit výsledek (všechny výsledky) se projeví najednou typicky jedna strojová instrukce více strojových instrukcí zde nastane problém → možnost vnějšího přerušení zdánlivou atomicitu je nutné zajistit jinak víceprocesorový systém zdánlivá ani skutečná atomicita problém neřeší řešení: je nutné zaměřit se na ochranu dat
Zákaz přerušení zákaz přerušení znemožní přepnutí kontextu lze ohraničit kritickou sekci na začátku zákaz, na konci povolení přerušení je to však privilegovaná instrukce její použití může zablokovat počítač nelze použít u preemptivního multitaskingu vyhrazena jen pro jádro operačního systému procesům musíme nabídnout jiné řešení běžně se používá uvnitř jádra OS je to nebezpečné a neřeší aktivní čekání
Instrukce TSL „Test and Set Lock“ nastaví proměnnou a vrátí její původní hodnotu celá tato akce musí být nepřerušitelná po výstupu z kritické sekce → proměnná na „false“ implementace v CPU speciální strojová instrukce instrukce prohození obsahu paměti s registrem strojové instrukce SWAP, XCHG softwarová implementace využijeme zákaz přerušení → služba jádra OS
Použití TSL TSL je před vstupem do kritické sekce nastaví proměnnou Lock na pravdu (zamčeno) vrátí předchozí stav této proměnné TSL umisťujeme do čekací smyčky → aktivní čekání na konci kritické sekce: proměnná je Lock nastavena na nepravdu (odemčeno) while TestAndSet(Lock) do { nothing }; ...kód kritické sekce... Lock:=false;
Semafory 1965 – popsal Dijkstra proměnná boolean z TSL nahrazena čítačem do kritické sekce lze vpustit více procesů je-li větší, než 0, je vstup umožněn při výstupu zvýšena hodnota proměnné o 1 operace Down (P) → před kritickou sekcí operace Down se zablokuje, je-li proměnná <= 0 je-li > 0, pak je snížena a ukončena (vstup povolen) operace Up (V) → na konci kritické sekce proměnná je zvýšena o 1 stále problém aktivního čekání
Čekání před kritickou sekcí aktivní čekání realizováno jako smyčka (neustále testování) zbytečně spotřebovává čas procesoru není vhodné pro víceúlohové systémy výhodné pro krátkodobé čekání tzv. spinlock() pasivní čekání realizováno frontou čekajících procesů odstraňuje problém aktivního čekání podobně jako blokování procesů při I/O
Pasivní čekání odstraňuje problémy aktivního čekání čekající proces nemá spotřebovávat čas CPU vytvoříme frontu čekajících procesů zablokovaný proces odsunut do fronty využijeme funkci jádra → sleep() nebo přesuneme proces mezi blokované při výstupu z kritické sekce volání průchodu frontou
Zamykání souborů pro zabránění souběhu v unixových systémech jen informativní (advisory) i když je na soubor aplikován zámek, jádro ho nevynutí všechny programy musí zámky respektovat funkce fcntl() a flock() → též na části souboru sdílené zámky též nazývány jako zámky pro čtení exkluzivní zámky též nazývány jako zámky pro zápis souborové zámky
Souborové zámky soubor signalizující zamčeno např. /etc/shadow.lock znamená: někdo si mění heslo, tak počkáme někdy název včetně PID procesu, který ho vytvořil opět jde o záležitost respektu, jádro nevynucuje používá se ve shellu a na FS bez podpory zámků např. starší verze NFS bez lock démona vytvoření musí být atomická operace v shellu „noclobber“ nebo vytvoření adresáře v zásadě poměrně komplikovaná logika problém „opuštěných zámků“ (anglicky: stale lock file)
Uváznutí – deadlock dva nebo více procesů čeká na událost, ke které by došlo jen pokud by jeden z nich mohl pokračovat souvisí se zamykáním (viz dříve souběh) je možná detekce uváznutí čekání ukončí buď OS nebo správce problém uváznutí v jádře OS → reboot v běžném životě se řeší couváním program (resp. CPU) couvat neumí couvat umí SQL server (rollback)
Uváznutí (v dopravě)
Uváznutí (v počítači) nastane, když je nevhodná obsluha I/O A tiskne na tiskárnu → výhradní přístup B čte z diskety → výhradní přístup A potřebuje načíst další data z diskety → čeká na uvolnění diskety B potřebuje vytisknout data na tiskárnu → čeká na uvolnění tiskárny došlo k vzájemnému čekání → uváznutí
BKL Big Kernel Lock jednoduchý zámek v jádře pro SMP jádro hlídá jakýkoliv zápis do datových struktur jádra vše je pozastaveno, dokud se věc nevyřeší i když by mohly proběhnou souběžně (v případě, kdy se zapisuje do nekonfliktních dat) umožnil okamžité nasazení UP jádra na SMP ovšem za cenu častého (zbytečného) čekání dnes BLK v jádře Linuxu již dlouho neexistuje Microsoft se pochlubil u W7 (snížení 25% režie) avšak kompletní odstranění BKL nepotvrdil
Meziprocesová komunikace soubor sdílená paměť mapování souborů do paměti signály zasílání zpráv roura pojmenovaná roura IPC socket zamykání souborů
Soubor nejjednodušší výměna dat mezi procesy dočasné soubory v unixových systémech v adresáři /tmp, /var/tmp všichni mají právo zápisu → mohou si vzájemně škodit používá se sticky bit → nelze si vzájemně mazat i přes „w“ i tak vyžaduje vytváření dočasných souborů speciální zacházení zejména u privilegovaných procesů je riziko poměrně velké též problém souběhu → náhodné názvy, zamykání komunikace je však poměrně těžkopádná velká režie (zápis na HDD) mají však všechny systémy → přenositelnost
Sdílená paměť procesy jsou normálně odděleny kromě threadů, které mají sdílenou paměť záměrně sdílená paměť je shodná s částí jiného procesu při zápisu problém souběhu řeší se zamykáním, synchronizačními primitivy funkce pro ovládání definuje POSIX definuje vytvoření, připojení, získání ukazatele pak zápisy i čtení, odpojení, zrušení sdílené paměti zaručuje přenositelnost
Příklad $ ipcs -m ------ Shared Memory Segments -------- key shmid owner perms bytes nattch status 0x790068c1 6160388 apache 666 808 0 $ ipcrm shm 6160388 nejprve jsou vypsány sdílené segmenty paměti (ipcs) druhý příkaz (ipcrm) zruší sdílený segment paměti (zůstane-li chybně po programu) mnoho programů pro GUI využívá sdílenou paměť pro komunikaci výše je sdílená paměť démona WWW serveru Apache uživatel vidí jen oblasti, do kterých má přístup uživatel root vidí všechny oblasti v systému v jazyce C se používají funkce shmget(), shmat() apod.
Mapování souborů do paměti původně metoda nahrazující klasické operace otevření, čtení, zápis, posun ukazatele, zavření nevýhodou je neustále kopírování dat mezi cache, bufferem a paměťovým prostorem procesu využívá mechanismu „výpadku stránky“ odkládání nepoužívaných částí paměti na disk využíváno u stránkování paměti lze využít i pro meziprocesovou komunikaci namapovaný soubor může být sdílen více procesy samozřejmě je nutné řešit souběh atp.
Příklad používá se funkce mmap() otevření souboru pomocí open() získaný deskriptor jako parametr mmap() na (zvolené) adrese v paměti bude obsah souboru pro ni definujeme délku okna a offset obsahu souboru ukončení pomocí munmap() zrušení mmap() též ukončením programu
Signály jednoduchá meziprocesová komunikace implementováno v jádře OS asynchronní signalizace mezi procesy v unixových OS může odesílat signál i jádro OS lze poslat jen vlastním procesům správce (root) může poslat signál všem procesům proces zpracovává signál vyvoláním procedury implicitní akce, ignorování signálu, vlastní obsluha signálu ne všel lze předefinovat (KILL bohužel, resp. naštěstí nejde) při zpracování volat jen bezpečné funkce (! reentrantnost) odesláním signálu systémovým voláním kill()
Syscall: kill() název podle signálu KILL signály odlišeny názvy, ty mapovány na čísla HUP – „zavěšení“ + ukončení, dnes rekonfigurace INT – přerušení (z terminálu CTRL+c) QUIT – ukončení + core dump KILL – nepodmíněné ukončení procesu („vražda“) nelze ve stavu D (proces je v jádře, čeká na dokončení I/O) SEGV – porušení ochrany paměti PIPE – signalizace rozpadu roury (ukončení skupiny) TERM – slušná žádost o ukončení procesu STOP – pozastavení procesu CONT – obnovení běhu procesu
Příkaz kill zasílání signálů z příkazového řádku kill -l → vypíše seznam signálů + jejich čísla kill <PID> zaslání signálu TERM (žádost o ukončení) <PID> je číslo procesu signál lze posílat jen svým procesům, root může všem kill -1 <PID> nebo kill -HUP <PID> dnes někdy znovunačtení konfigurace (rekonfigurace) kill -9 <PID> nebo kill -KILL <PID> bezpodmínečné ukončení procesu
Zasílání zpráv univerzálnější, než signály mezi procesy lze přenášet i data implementace v jádře nebo jako sdílená paměť řešení mezních situací synchronní a asynchronní jednosměrné, obousměrné spolehlivý přenos nebo bez záruk nutnost implementovat fronty, potvrzování zpráv řešení duplikace, ztráty, příjemce skončil atd.
Kolona (roura) propojení příbuzných procesů propojení přes deskriptory jednosměrné spojení (jeden zapisuje, druhý čte) vytváří se skupina procesů jádro posílá při přerušení roury signál SIGPIPE skupina reaguje ukončením („broken pipe“) v paměti kruhový vyrovnávací paměť – buffer typicky se využívá v příkazovém řádku grep ro /etc/passwd | sort
Pojmenovaná roura umožňuje spojení nepříbuzných procesů definuje POSIX styčné místo je speciální soubor typu roura název lze nějak předat nepříbuzným procesům vytvořená pojmenovaná roura „přežije“ ukončení procesů data vyměňována v paměti (buffer) pouze jednosměrná komunikace (FIFO) jeden proces zapisuje, další čte
IPC socket též tzv. Unix Domain Socket, definuje POSIX speciální soubor, ale implementováno v RAM obdoba síťové komunikace od roury přidává obousměrnou komunikaci navíc možnost více klientů například PostgreSQL server + klient /tmp/.s.PGSQL.5432 klient otevře a připojí se