Linux - Procesy (Processes)

Rozměr: px
Začít zobrazení ze stránky:

Download "Linux - Procesy (Processes)"

Transkript

1 Linux - Procesy (Processes) Běžící instance programu se nazývá proces. Například dvě okna terminálu jsou instancemi stejného terminálového programu, ale jsou to dva různé procesy. V každém okně běží shell, který je zase jiný proces. Spuštěním programu v tomto shellu se vytvoří další nový proces. Více spolupracujících procesů v jedné aplikaci jí umožňuje dělat více věcí najednou. #include <unistd.h> typedef int pid_t; typedef pid_t pid_t; getpid(2) #include <unistd.h> pid_t getpid(void); vrací jedinečné pid aktuálního procesu Př. Napište program, který vypíše pid svého procesu. Program nemažte, budete ho rozšiřovat o další probírané funkce! getppid(2) #include <unistd.h> pid_t getppid(void); vrací jedinečné pid rodiče aktuálního procesu každý proces má rodiče (kromě procesu init), procesy jsou uspořádány do stromové struktury s procesem init jako vrcholem Př. Vypište pid rodiče. ps(1) ps [options] defaultně (bez parametrů) vypíše procesy kontrolované terminálem, ve kterém byl ps spuštěn přepínači lze určit, jaké procesy a informace o nich se mají vypsat, např. -e pro všechny procesy, -u user pro procesy uživatele user, -l pro dlouhý formát výpisu, -o pro vlastní formát, atd. Př. Vypište si všechny své procesy ve tvaru STAT USER PID PPID NICE CMD kill(1) kill pid... ukončí procesy pid... (pošle jim signál SIGTERM) Př. Spusťte si program top a ukončete ho pomocí SIGTERM. Vytvoření procesu system(3) #include <stdlib.h> int system (const char * string); spustí příkaz ve string voláním /bin/sh -c string její používání není bezpečné (blokuje některé signály), doporučuje se používat fork a exec vrací 127, pokud shell nelze spustit, -1 při jiné chybě, jinak návratový kód příkazu

2 Př. Spusťte příkaz ls -la. fork(2) #include <unistd.h> pid_t fork(void); vytvoří stejný proces jako svého potomka, který se liší jen v pid a ppid rodičovský proces i jeho potomek pokračují ve vykonávání programu od místa volání fork v rodiči vrací pid potomka, v potomkovi nulu, při chybě -1 v rodiči, potomek se nevytvoří Př. Vytvořte potomka, který vypíše svoje pid. exec(3) execve(2) #include <unistd.h> int execl( const char *path, const char *arg,...); int execlp( const char *file, const char *arg,...); int execle( const char *path, const char *arg,..., char * const envp[]); int execv( const char *path, char *const argv[]); int execvp( const char *file, char *const argv[]); int execve (const char *filename, char *const argv [], char *const envp[]); tyto funkce nahradí aktuální program jiným první argument je soubor (včetně cesty), který se má vykonat const char *arg,... jsou arg0,... spuštěného programu, poslední prvek seznamu musí být NULL char *const argv[] je seznam arg0,... spuštěného programu, poslední prvek pole musí být NULL char * const envp[] je seznam proměnných prostředí spuštěného programu, poslední prvek seznamu musí být NULL, prvky seznamu jsou očekávány ve tvaru "PROMENNA=hodnota" funkcím execvp a execlp stačí jen jméno souboru ke spuštění, který se hledá ve vyhledávací cestě (proměnná PATH) pokud se funkce ukončí (vždy -1), je to chyba Při vytváření nového procesu se nejdříve zavolá fork, který vytvoří kopii aktuálního procesu, a pak exec, který nový proces změní na instanci programu, který chceme spustit. Př. Spusťte příkaz date +%s pomocí fork a exec. Linux plánuje procesy nezávisle, není zaručeno, který poběží dřív, jak dlouho poběží. nice(1) nice [OPTION]... [COMMAND [ARG]...] spustí program s jinou prioritou (defaultně má nový proces prioritu 0) rozsah priorit je -20 (nejvyšší) až 19 (nejnižší) pro novou prioritu je přepínač -n jenom root může spustit proces se zápornou prioritou Př. Spusťte program yes s nice 5. Zkontrolujte si to pomocí ps. Zkuste -5. renice(1) renice priority [[-p] pid...] [[-g] pgrp...] [[-u] user...] změní prioritu běžících procesů procesy lze určit pomocí pid nebo všechny procesy uživatele user (defaultně pid) priority může být [+-]číslo, priority = nice jenom root může zvyšovat prioritu (snižovat nice)

3 Př. Zvyšte nice programu yes na 19. Zkontrolujte si to pomocí ps. Zkuste nice snížit. nice(2) #include <unistd.h> int nice(int inc); přidá inc k prioritě volájícího procesu jenom root může zadat záporný inc vrací 0, při chybě -1 Př. Zvyšte nice potomka. sleep(3) #include <unistd.h> unsigned int sleep(unsigned int seconds); "uspí" proces na seconds sekund, nebo ho probudí neignorovaný signál vrací 0, pokud čas uplynul, jinak zbývající počet sekund Př. Pozdržte potomka 2 sekundy a vypište datum znovu. Ukončení procesu exit(3) #include <stdlib.h> void exit(int status); normálně ukončí program, status je vrácen rodiči funkce se neukončí Př. Ošetřete neúspěšný fork pomocí exit. int main(int argc, char *argv[], char *envp[]); ukončení main je normální ukončení, návratová hodnota vrácena rodiči návratová hodnota funkce main je sice int, ale používat by se měly jen hodnoty 0-127, kódy nad 128 včetně mají speciální význam - když je proces ukončen signálem, návratová hodnota je číslo signálu Př. Ukončete korektně rodiče i potomka návratem z main. abort(3) #include <stdlib.h> void abort(void); abnormálně (s core souborem) ukončí program funkce se neukončí Př. Ošetřete neúspěšný exec pomocí abort. Potomek může proběhnout až po ukončení předka, protože oba procesy jsou plánovány nezávisle. To je někdy nežádoucí, někdy chceme, aby rodič počkal, až se potomek ukončí. wait(2) #include <sys/types.h> #include <sys/wait.h> pid_t wait(int *status) zastaví proces, dokud se neukončí nějaký potomek, nebo pokud proces dostane ukončující signál nebo se volá nějaký signal-handler pokud už potomek skončil (zombie), funkce se hned ukončí, všechny prostředky systému přidělené potomkovi

4 jsou uvolněny pokud status není NULL, na místo, kam ukazuje, se uloží informace o potomkovi vrací pid potomka, při chybě -1 Př. V rodiči počkejte na potomka. waitpid(2) #include <sys/types.h> #include <sys/wait.h> pid_t waitpid(pid_t pid, int *status, int options); zastaví proces, dokud se neukončí potomek s ID pid, nebo pokud proces dostane ukončující signál nebo se volá nějaký signal-handler pokud už potomek skončil (zombie), funkce se hned ukončí, všechny prostředky systému přidělené potomkovi jsou uvolněny pokud status není NULL, na místo, kam ukazuje, se uloží informace o potomkovi pokud je pid -1, funkce se chová jako wait vrací pid potomka, při chybě -1, nebo 0, pokud žádný potomek neskončil a v options bylo WNOHANG Ze status (int) lze získat různé informace o potomkovi těmito makry: WIFEXITED(status) vrací nenulové číslo, pokud potomek spončil normálně WEXITSTATUS(status) vrací návratový kód potomka smí se vyhodnotit, jen pokud WIFEXITED je nenulové Př. Vypište návratový kód potomka. WIFSIGNALED(status) vrací nenulové číslo, pokud potomka ukončil signál WTERMSIG(status) vrací číslo signálu, který ukončil potomka smí se vyhodnotit, jen pokud WIFSIGNALED je nenulové Zombie procesy Co se stane, když potomek skončí a rodič na něj nečeká voláním wait? Informace o jeho ukončení budou dočasně ztraceny a z něj se stane zombie. Zombie je proces, který skončil, ale ještě nebyl ze systému odstraněn, to je povinnost rodiče. Potom, co se proces ukončí, stane se z něj zombie, dokud si informace o jeho ukončení nevyzvedne jeho rodič pomocí wait. Pokud si rodič tyto informace nevyzvedne nikdy (ani po svém ukončení), zombie adoptuje proces init a odstraní jej ze systému. OTÁZKA: Co se s potomkem stane, když rodič skončí dřív než on? Bude bez rodiče? PŘÍKLAD Další funkce týkající se procesů jsou: getuid(2) / setuid(2) geteuid(2) / seteuid(2) getgid(2) / setgid(2) getegid(2) / setegid(2) clone(2) vfork(2) getpriority(2) / setpriority(2)

5 wait3(2) wait4(2) Linux - Signály (Signals) Signály je mechanizmus pro komunikaci a manipulaci s procesy. Signál je speciální zpráva zaslaná procesu. Signály jsou asynchronní, tj. když jej proces obdrží, ihned ho obslouží, bez dokončení aktuální funkce (ta se dokončí až pak). Každý signál je specifikován svým číslem, v programech se však používají jména definovaná v <bits/signum.h>. Všechny signály jsou pak popsány v signal(7). Zaslání signálu raise(3) #include <signal.h> int raise (int sig); pošle signál sig vlastnímu procesu vrací 0, při chybě nenulové číslo Př. Vytvořte program, který si pošle SIGTERM a tím se tedy ukončí. Program nemažte, budete ho rozšiřovat o další probírané funkce! Proces může poslat signál jinému procesu. Např. ho ukončit zasláním SIGTERM nebo SIGKILL. OTÁZKA: Jaký je rozdíl mezi SIGTERM a SIGKILL? kill(1) kill [signal] pid... pošle každému procesu (pid) SIGTERM (pokud není signal zadán), nebo signál signal přepínač -l vypíše všechny signály Př. Spusťte si program top a zabijte ho pomocí SIGKILL. kill(2) #include <sys/types.h> #include <signal.h> int kill(pid_t pid, int sig); pošle signál sig procesu s ID pid vrací 0, při chybě -1 Př. Nahraďte funkci raise funkcí kill. Pro zaslání příkazu procesu jsou rezervovány dva uživatelské signály, SIGUSR1 a SIGUSR2. Někdy se pro tento účel používá i SIGHUP, na "probuzení" nebo "restart" programu. strsignal(3) #define _GNU_SOURCE #include <string.h> char *strsignal(int sig); vrátí řetězec popisující singál s číslem sig psignal(3) #include <signal.h> void psignal(int sig, const char *s); napíše na stderr zprávu tvaru s: sig_d, kde sig_d je popis signálu sig

6 pause(2) #include <unistd.h> int pause(void); "uspí" proces, dokud nepřijde signál při přerušení (signálem) vrací -1 Př. Uspěte program a z jiného terminálu mu pošlete SIGCONT. Obdržení signálu Co proces udělá po obdržení signálu záleží na určení signálu. Každý signál má defaultní určení, která určuje, co se stane, když program nestanovuje jinak. Pro většinu signálů jej může program ignorovat nebo zavolat speciální funkci (signal-handler). Při volání handleru se program zastaví, vykoná se handler a pak program pokračuje. Např. SIGBUS (bus error), SIGSEGV (segmentation violation) a SIGFPE (floating point exception) jsou zaslány procesu, když se pokouší provést nepřípustnou akci. Defaultní určení signálu je ukončení procesu a vytvoření core souboru. signal(2) #define _GNU_SOURCE #include <signal.h> typedef void (*sighandler_t)(int); sighandler_t signal(int signum, sighandler_t action); instaluje nový signal-handler pro signál s číslem signum action může být: signal-handler funkce SIG_IGN pro ignorování signálu SIG_DFL pro defaultní určení signálu parametr signal-handler funkce je číslo signálu defaultní určení signálů jsou popsány v signal(7) nelze instalovat handler na SIGKILL a SIGSTOP sighandler_t je GNU rozšíření vrací předchozí signal-handler, nebo při chybě SIG_ERR Př. Napište signal-handler, který bude bude počítat, kolik signálů SIGTERM program dostane. Při SIGQUIT se ukončí a vypíše počet obdržených signálů SIGTERM. Pošlete programu pár signálů SIGTERM a pak SIGQUIT. Protože signály jsou asynchronní, program by mohl být při zpracovávání signálu v nekonzistentním stavu a proto by se v signal-handleru neměly volat knihovní a systémové funkce a vykonávat I/O operace. signal-handler by měl vykonat jen práci nezbytně nutnou k ošetření signálu. Je možné, že signal-handler bude přerušen obdržením jiného signálu. Pokud se to stane, je velmi těžké to debugovat, pokud je tam chyba, proto by se měl dávat velký pozor na to, co se v signal-handleru provádí. Nebezpečné je dokonce i přiřazení do globální proměnné, protože může probíhat ve více instrukcích, a druhý signál se může vyskytnout mezi nimi. Tato globální proměnná by měla být typu sig_atomic_t, do kterého se přiřazuje v jedné instrukci (protože je to int). #include <signal.h> typedef int sig_atomic_t; typedef sig_atomic_t sig_atomic_t; Př. Proměnnou, ve které počítáte počet signálů SIGTERM, změňte na typ sig_atomic_t. alarm(2) #include <unistd.h> unsigned int alarm(unsigned int seconds); pošle procesu SIGALRM za seconds sekund pokud seconds je 0, nic se nenačasuje vrací zbývající počet sekund do zaslání signálu, nebo 0, pokud není načasován žádný alarm

7 Př. Zařiďte, aby se program sám ukončil po 10 sekundách běhu. Procesy a signály Proces může skončit abnormálně, jako odpověď na signál. Např. SIGBUS, SIGSEGV a SIGFPE způsobí ukončení procesu. Další signály slouží k explicitnímu ukončení. SIGINT je procesu zaslán, když se jej uživatel snaží ukončit pomocí C-C. SIGTERM posílá kill. Při volání funkce abort si proces sám pošle SIGABRT, což jej také ukončí s core souborem. Nejmocnější je SIGKILL, který jej okamžitě ukončí a program tomu nemůže nijak zabránit (blokovat, ingnorovat, ošetřit). Čekání na potomka pomocí wait proces blokuje, dokud se potomek neukončí. Většinou ale chceme, aby i rodič pokračovat dál. Jak se ale postarat o potomka ihned po jeho ukončení, tak, aby nezůstávali zombie? Jedna možnost je periodicky volat wait3 nebo wait4, které lze volat i v neblokujícím módu. Mnohem lepší je ale rodiče informovat o ukončení potomka, pomocí signálu. Když se ukončí potomek, systém pošle rodiči signál SIGCHLD, který defaultně nemá žádné určení. Funkci wait tedy zavoláme v signal-handleru signálu SIGCHLD. PŘÍKLAD Další funkce týkající se signálů jsou: sigaction(2) sigprocmask(2) sigpending(2) sigsuspend(2) sigblock(2) siggetmask(2) sigsetmask(2) sigmask(2) siginterrupt(2) sigpause(2) Linux - Vlákna (Threads) Vykonávání programu může být rozděleno do více "proudů", vláken, které běží paralelně. Vlákna tedy, stejně jako procesy, umožňují aplikaci dělat více věcí najednou. Vlákno existuje uvnitř procesu. Při spuštění programu se vytvoří proces a v něm jedno vlákno, které může spustit další. Všechna tato vlákna běží paralelně ve stejném procesu, ale mohou vykonávat různé části (kód) programu. Dvě různá vlákna téhož procesu sdílejí stejnou paměť, deskriptory souborů a jiné systémové zdroje přidělené celému procesu. Protože proces a všechna jeho vlákna vykonávají jeden program, když jedno vlákno zavolá exec, všechna ostatní vlákna jsou ukončena. GNU/Linux implementuje API vláken podle standardu POSIX (pthreads). Všechny funkce a datové typy jsou deklarovány v <pthread.h>. Funkce nejsou ve standardní C knihovně, ale v knihovně libpthread, takže je potřeba linkovat s parametrem -lpthread. Vytvoření vlákna #include <bits/pthreadtypes.h> typedef unsigned long int pthread_t; pthread_self(3) pthread_t pthread_self(void); vrací id vlákna Př. Napište program, který vypíše ID svého hlavního vlákna. Program nemažte, budete ho rozšiřovat o další probírané funkce! pthread_equal(3)

8 int pthread_equal(pthread_t thread1, pthread_t thread2); vrací nenulové číslo, když thread1 a thread2 jsou id téhož vlákna, jinak 0 Po spuštění každé vlákno vykonává funkci vlákna. Když tato funkce skončí, skončí i vlákno. Má jediný parametr void*, vrací také void*. pthread_create(3) int pthread_create(pthread_t * thread, pthread_attr_t * attr, void * (*start_routine)(void *), void * arg); vytvoří nové vlákno, které vykoná funkci start_routine s parametrem arg attr specifikuje atributy vlákna (viz pthread_attr_init), pokud je NULL, jsou defaultní: joinable, defaultní priorita vrací 0 a id vlákna na místo, kam ukazuje argument thread, při chybě nenulové číslo funkce se vrací ihned, obě vlákna pak pokračují asynchronně Př. Vytvořte vlákno s defaultními atributy a bez parametrů funkce vlákna. Při vytváření atributů vlákna se postupuje takto: vytvoří se struktura pthread_attr_t pomocí pthread_attr_init se inicializuje na defaultní hodnoty změní se hodnoty ve struktuře zavolá se pthread_create a předá se jí tato struktura pthread_attr_destroy strukturu zruší, ale nedealokuje (pokud je vytvořena dynamicky) S jednou strukturou je možné vytvořit více vláken a je možné ji zrušit po vytvoření vlákna. pthread_attr_init(3) int pthread_attr_init(pthread_attr_t *attr); inicializuje strukturu atributů defaultními hodnotami vrací 0, při chybě nenulové číslo pthread_attr_destroy(3) int pthread_attr_destroy(pthread_attr_t *attr); zruší strukturu atributů, před dalším použitím se musí znova inicializovat vrací 0, při chybě nenulové číslo v Linuxu nedělá nic pthread_attr_setdetachstate(3) pthread_attr_getdetachstate(3) int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate); int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate); nastaví(vrací) atribut z(do) druhého parametru vrací 0, při chybě nenulové číslo atribut detachstate může být: PTHREAD_CREATE_JOINABLE - vlákno bude joinable, defaultní PTHREAD_CREATE_DETACHED - detached Joinable vlákno není po skončení automaticky odstraněno ze systému, jeho status ukončení je udržován, dokud si ho nevyzvedne jiné vlákno pomocí pthread_join (stejné jako zombie u procesu). Detached vlákno je naopak hned po skončení automaticky odstraněno a nelze získat jeho informace o ukončení pomocí pthread_join.

9 Př. Změňte vytvářené vlákno na detached. Typ argumentu funkce vlákna je void*, nelze tedy poslat data (>4B) přímo. Předává se ukazatel na strukturu dat. Tato struktura ale nesmí být lokální v jednom vláknu (př. hlavním), protože by mohlo skončit dříve než ostatní, která tuto strukturu používají. Pokud je lokální, možným řešením je ve vláknu počkat, až ostatní vlákna skončí. Struktura se nesmí dealokovat dřív, než vlákna, která ji používají, skončí. Př. Předejte funkci vlákna 2 řetězce jako parametry, ty spojte a výsledek vraťte jako návratovou hodnotu funkce vlákna. pthread_join(3) int pthread_join(pthread_t th, void **thread_return); pozastaví vlákno, dokud neskončí vlákno specifikované pomocí th pokud thread_return není NULL, vrátí návratovou hodnotu funkce vlákna na místo, kam ukazuje, pokud je vlákno zrušeno, je tam PTHREAD_CANCELED jen jedno vlákno může čekat na skončení jiného vlákna vrací 0, při chybě nenulové číslo vlákno nesmí čekat samo na sebe, to je deadlock! Př. Počkejte na dokončení vlákna a vypište výsledek spojení. pthread_detach(3) int pthread_detach(pthread_t th); "přepne" vlákno na detached, pokud jiné vlákno nečeká na jeho ukončení vrací 0, při chybě nenulové číslo Ukončení vlákna pthread_exit(3) void pthread_exit(void *retval); ukončí vlákno s návratovým kódem retval nikdy se neukončuje pthread_cancel(3) int pthread_cancel(pthread_t thread); pošle vláknu, specifikovanému pomocí thread, požadavek na ukončení vrací 0, při chybě nenulové číslo Vlákno často vykonává kód, který nesmí být přerušen. To je zajištěno tím, že vlákno samo si může určit místa, kde může být zrušeno a kde ne, pomocí svého stavu: asynchronně zrušitelné - může být zrušeno kdekoliv synchronně zrušitelné - může být zrušeno až v určitých místech (body zrušení), požadavek je zaznamenán, defaultní při vytvoření vlákna nezrušitelné - požadavky na zrušení jsou ignorovány pthread_setcanceltype(3) int pthread_setcanceltype(int type, int *oldtype); změní typ reakce na zrušení vlákna na type type může být: PTHREAD_CANCEL_ASYNCHRONOUS - asynchronní

10 PTHREAD_CANCEL_DEFERRED - synchronní pokud oldtype není NULL, na místo, kam ukazuje, je uložen předchozí typ vrací 0, při chybě nenulové číslo pthread_testcancel(3) void pthread_testcancel(void); vytvoří bod zrušení existují implicitní body zrušení (viz man), př. pthread_join Př. Změňte vlákno na synchronně zrušitelné a vytvořte body zrušení před a po spojení. pthread_setcancelstate(3) int pthread_setcancelstate(int state, int *oldstate); změní stav zrušení vlákna na state state může být: PTHREAD_CANCEL_ENABLE - zrušitelný stav PTHREAD_CANCEL_DISABLE - nezrušitelný pokud oldstate není NULL, na místo, kam ukazuje, je uložen předchozí stav vrací 0, při chybě nenulové číslo umožňuje vymezení kritických sekcí - nepřerušitelný kód Př. Uzavřete spojení do kritické sekce. PŘÍKLAD Lokální uložení dat Vlákna sdílejí stejný adresový prostor. Někdy je ale potřeba, aby každé vlákno mělo vlastní kopii určité globální proměnné. Každé vlákno poskytuje lokální uložení dat (thread-specific data - TSD - area), kde se ukládají kopie globálních proměnných specifické pro každé vlákno. Proměnné v tomto uložení jsou indexovány přes klíče. Klíče jsou společné všem vláknům, hodnota proměnné je v každém vláknu jiná. pthread_key_create(3) int pthread_key_create(pthread_key_t *key, void (*destr_function) (void *)); vytvoří nový TSD klíč a uloží ho, kam ukazuje key, asociovaná hodnota je NULL pokud destr_function není NULL, je to funkce, která se zavolá po ukončení vlákna s hodnotou asociované proměnné jako parametrem, před jejím voláním je ke klíči asociován NULL vrací 0, při chybě nenulovou hodnotu pthread_key_delete(3) int pthread_key_delete(pthread_key_t key); zruší TSD klíč vrací 0, při chybě nenulovou hodnotu pthread_setspecific(3) int pthread_setspecific(pthread_key_t key, const void *pointer); změní hodnotu proměnné asociované s klíčem key na pointer

11 vrací 0, při chybě nenulovou hodnotu pthread_getspecific(3) void * pthread_getspecific(pthread_key_t key); vrací hodnotu proměnné asociované s klíčem key, při chybě NULL PŘÍKLAD OTÁZKA: Procesy versus vlákna? Najděte co nejvíc rozdílů. Další funkce týkající se vláken jsou: pthread_cleanup_push(3) / pthread_cleanup_pop(3) pthread_setschedparam(3) / pthread_getschedparam(3) pthread_kill(3) pthread_sigmask(3) sigwait(3) Linux - Meziprocesní komunikace (Interprocess communication, IPC) Nejjednodušší forma IPC je, že rodič může zjistit, jak skončil jeho potomek. Rodič může potomkovi sdělit informace také přes jeho argumenty a proměnné prostředí. Žádný z těchto mechanizmů ale rodiči neumožňuje s potomkem komunikovat za jeho běhu a už vůbec neumožňuje komunikaci dvou procesů, které nejsou ve vztahu rodič-potomek. Za určitý primitivní druh komunikace se dají považovat signály, ale "skutečná" komunikace znamená výměna informací čili dat. Např. klasické balení souboru dvojicí tar+gzip, tar cf - * gzip - > soubor.tar.gz, využívá mechanizmu roury (pipes). Druhy IPC se liší těmito kritérii: zda komunikují dva příbuzné (mající společného rodiče) nebo zcela cizí procesy zda komunikující proces může jen číst či jen zapisovat data počet procesů zapojených do komunikace zda jsou komunikující procesy synchronizovány, např. čtecí proces čte, až je co číst Sdílená paměť (Shared memory) Jednou z nejjednodušších metod IPC je sdílená paměť, která umožňuje dvěma a více procesům přistupovat ke stejné oblasti paměti. Sdílená paměť je nejrychlejší formou IPC, protože procesy sdílí stejnou paměť a pro přístup do ní není potřeba žádné systémové volání. Protože ale systém neposkytuje žádnou formu synchronizace, musíme si ji zajistit sami. Např. dva procesy by neměly zapisovat zároveň na stejné místo v paměti. Tradičním nástrojem pro synchronizaci jsou semafory. Pro použití sdílené paměti ji jeden proces musí alokovat. Všichni si ji pak "připojí". Po používání ji "odpojí" a ten proces, který ji alokoval, ji dealokuje. Sdílená paměť se alokuje po celočíselných násobcích velikosti stránky paměti. getpagesize(2) #include <unistd.h> size_t getpagesize(void); vrací velikost (počet bytů) stránky paměti systému shmget(2) #include <sys/ipc.h> #include <sys/shm.h> int shmget(key_t key, int size, int shmflg); je vytvořen úsek paměti velikosti nahoru zaokrouhlené size na násobek stránky, pokud v key je IPC_PRIVATE anebo ke key není asociován žádný úsek sdílené paměti, a v shmflg je IPC_CREAT key je libovolný zvolený číselný klíč

12 v shmflg může být: IPC_CREAT - vytvoří nový úsek, pokud toto není, najde se úsek asociovaný ke klíči key IPC_EXCL - používá se s IPC_CREAT, chyba pokud úsek existuje mode_flags - specifikuje práva k úseku, definována v <sys/stat.h>, může být: S_IRUSR, S_IWUSR - čtení, zápis pro vlastníka úseku S_IROTH, S_IWOTH - pro ostatní vrátí identifikátor sdílené paměti asociovaný ke klíči key, při chybě -1 existují limity pro úsek sdílené paměti, viz man Př. Napište program, který vytvoří sdílenou paměť o velikosti stránky paměti s právy zápisu pro sebe a čtení pro ostatní. Potomek po fork zdědí připojené úseky, po exec a exit jsou všechny připojené úseky odpojeny, ale ne dealokovány! shmat(2) #include <sys/types.h> #include <sys/shm.h> void *shmat ( int shmid, const void *shmaddr, int shmflg ); připojí úsek sdílené paměti identifikovaný identifikátorem shmid na adresu shmaddr pokud je shmaddr NULL, systém si sám najde volnou adresu pokud je v shmflg SHM_RND, adresa se zaokroulí dolů na násobek stránky, jinak adresa musí být už zaokrouhlená pokud je v shmflg SHM_RDONLY, pameť je připojena jen pro čtení, jinak i pro zápis (pokud to práva dovolují) při chybě vrací -1, jinak adresu připojené paměti Př. Uložte něco (např. text) do sdílené paměti. shmdt(2) #include <sys/types.h> #include <sys/shm.h> int shmdt ( const void *shmaddr); odpojí sdílenou paměť na adrese shmaddr, paměť musí být připojená při chybě vrací -1, jinak 0 Př. Před ukončením programu sdílenou paměť odpojte. shmctl(2) #include <sys/ipc.h> #include <sys/shm.h> int shmctl(int shmid, int cmd, struct shmid_ds *buf); zjistí informace o úseku (identifikovaného pomocí shmid) sdílené paměti, mění práva a dealokuje úsek informace vrací do struktury shmid_ds, viz man cmd může být: IPC_STAT - vrací informace, potřebuje právo na čtení úseku IPC_SET - nastavuje práva IPC_RMID - označí úsek pro zrušení, ten se zruší až po posledním odpojení, zrušit úsek může jen ten, kdo ho vytvořil nebo root vrací 0, při chybě -1 Př. Vytvořte potomka, který si zjistí informace o této paměti a z nich vypíše její velikost, pak přečte, co tam rodič zapsal a vypíše to. Každý úsek sdílené paměti musí být explicitně zrušen, protože systém ji nezruší ani po ukončení procesů! Př. Před ukončením programu sdílenou paměť zrušte.

13 ipcs(8) ipcs -m vypíše úseky sdílené paměti Př. Podívejte se, zda v systému nezůstaly úseky nepoužívané sdílené paměti. ipcrm(8) ipcrm shm id... zruší úseky sdílené paměti specifikované pomocí id Př. Zrušte úseky nepoužívané sdílené paměti. PŘÍKLAD Mapovaná paměť (Mapped memory) Mapovaná paměť umožňuje různým procesům komunikovat přes sdílený soubor. Může se zdát, že je to stejné jako sdílená paměť, ale jsou zde technické rozdíly. Mapovaná paměť se dá použít jak pro komunikaci, tak pro jednoduchý přístup do souboru. Linux rozdělí soubor na paměťové stránky a ty zkopíruje do paměti, takže proces k nim může přistupovat jako do paměti, číst i zapisovat. mmap(2) #include <unistd.h> #include <sys/mman.h> caddr_t mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset); namapuje length bytů na offsetu offset ze souboru specifikovaném deskriptorem fd na adresu start (v praxi se ovšem dává NULL - systém sám vybere adresu) prot specifikuje práva: PROT_EXEC - z paměti lze spouštět PROT_READ - číst PROT_WRITE - zapisovat flags určuje typ mapování, může být jen jedno z: MAP_SHARED - sdílení mapování souboru s ostatními procesy, které ho mapují také, zápis je nebufferovaný, okamžitý MAP_PRIVATE - privátní mapování vrací ukazatel na mapovanou paměť, při chybě -1 munmap(2) #include <unistd.h> #include <sys/mman.h> int munmap(void *start, size_t length); zruší mapování paměti na adrese start délky length vrací 0, při chybě -1 mapovaná paměť se automaticky zruší po skončení procesu Různé procesy mohou komunikovat použitím mapované paměti téhož souboru a použití MAP_SHARED. Stejně jako u sdílené paměti je potřeba explicitně zajistit synchronizaci, např. semafory nebo zamykáním souboru. Časté použití mapované paměti je také pro rychlé čtení a zápis do souboru nebo ukládání datových struktur do souboru. OTÁZKA: Když ukládaná datová struktura obsahuje ukazatele, po načtení této struktury budou tyto ukazatele neplatné. Proč? Jaké shody okolností by musely nastat, aby byly platné? PŘÍKLAD Další funkce týkající se sdílené nebo mapované paměti jsou: msync(2)

14 Roury (Pipes) Roura umožňuje jednosměrnou komunikaci. Data zapsaná do "zapisovacího konce" jsou čtena z "čtecího konce". Roury jsou sériová zařízení, data jsou čtena ve stejném pořadí, v jakém byla zapsána. Používají se ke komunikaci dvou vláken jednoho procesu nebo mezi rodičovským procesem a potomky. V shellu symbol vytvoří rouru. Např. ls less vytvoří dva potomky shellu, ls a less. Shell také vytvoří rouru spojující standardní výstup ls se standardním vstupem less. Kapacita roury je omezená. Pokud zapisující proces zapisuje rychleji než čtecí proces čte a roura už nemůže uchovat data, zapisovací proces je blokován, dokud se neuvolní místo. Pokud se proces pokouší číst z roury, ale není co číst, je blokován, dokud nebude co číst. Roura tedy automaticky synchronizuje dva procesy. pipe(2) #include <unistd.h> int pipe(int filedes[2]); vytvoří dva deskriptory souboru, ukazující na konce roury, a uloží je do filedes filedes[0] je pro čtení, filedes[1] pro zápis vrací 0, pří chybě -1 Deskriptory souboru, které vytvoří pipe, jsou platné jen v procesu a jeho potomcích. Při volání fork jsou deskriptory kopírovány do potomka, proto roura může spojovat pouze příbuzné procesy. Po volání fork mají jak rodič tak i potomek oba konce roury. Roura jako komunikační zařízení má však jen dva konce, proto se musí v rodiči i v potomkovi nepoužívané konce ihned uzavřít. Zvláště existence dvou zapisovacích konců roury způsobuje podivné chování. Při čtení z roury, která má zapisovací konec uzavřený, vrací read hodnotu 0. A při zápisu do roury, která má uzavřený čtecí konec, obdrží proces signál SIGPIPE. Př. Napište program, který vytvoří rouru a potomka. Jeden proces pak do roury něco zapíše, druhý to přečte a vypíše. K otevření konce roury ve formě streamu (FILE *) použijte funkci fdopen, k uzavření zase close. Často je potřeba vytvořit potomka tak, aby jeden konec roury byl jeho standardní vstup nebo výstup. dup(2) dup2(2) #include <unistd.h> int dup(int oldfd); int dup2(int oldfd, int newfd); funkce vytvoří kopii deskriptoru oldfd starý i nový deskriptor jsou zaměnitelné, sdílejí zámky, pozici, nesdílejí příznak uzavření při ukončení procesu dup2 vytvoří kopii jako newfd, který popřípadě nejdřív uzavře vrací nový deskriptor, při chybě -1 Př. Přesměrujte std. vstup potomka na čtecí konec roury a změňte program potomka na sort. V rodiči do roury zapište několik vět. Roura má buffer určité velikosti, proto po zápisu vět zavolejte fflush. Deskriptor std. vstupu je STDIN_FILENO. Běžné použítí rour je zasílání nebo příjímání dat od programu, který běží jako potomek. K vytvoření tohoto stavu je potřeba volat postupně funkce pipe, fork, dup2, exec a fdopen. Volání všech těchto funkcí nahrazují funkce popen a pclose. popen(3) #include <stdio.h> FILE *popen(const char *command, const char *type); vytvoří proces voláním pipe, fork a spuštěním shellu type může být jen jedno z: "r" - proces bude číst data od potomka, funkce vrátí standardní výstup potomka "w" - proces bude zapisovat data pro potomka, funkce vrátí standardní vstup potomka command je příkaz pro shell, spuštěn pomocí /bin/sh -c command vytvořený stream by měl být uzavřen pomocí pclose, ne fclose

15 při chybě (fork, pipe nebo alokace paměti) vrací NULL pclose(3) #include <stdio.h> int pclose(file *stream); uzavře stream vytvořený pomocí popen, čeká, až se spuštěný příkaz ukončí vrací návratový kód spuštěného příkazu, při chybě -1 Př. Poslední úkol (sort) proveďte pomocí popen a pclose. PŘÍKLAD FIFO FIFO (First In, First Out) je roura, která je souborem. Jakýkoliv proces může číst nebo zapisovat do FIFO, procesy nemusí být příbuzné. FIFO musí být otevřená pro čtení i zápis dřív, než se z ní může něco číst nebo do ní zapisovat. Otevření pro čtení proces blokuje, dokud ji neotevře jiný proces pro zápis a opačně. FIFO se někdy nazývá pojmenovaná roura. mkfifo(1) mkfifo [OPTION] NAME... vytvoří FIFO se jménem NAME volbou -m (--mode) se nastavují práva, která musí obsahovat práva čtení a zápisu Př. Vytvořte FIFO, např. /tmp/fifo. V jednom terminálu z ní čtěte pomocí cat < /tmp/fifo. V jiném do ní zapisujte pomocí cat > /tmp/fifo a zadávejte věty (ukončené ENTER). Sledujte, jak se věty vypisují v prvním terminálu. Zadávání vět ukončete pomocí C-D. Smažte FIFO. mkfifo(3) #include <sys/types.h> #include <sys/stat.h> int mkfifo ( const char *pathname, mode_t mode ); vytvoří FIFO se jménem pathname mode specifikuje práva, která musí obsahovat práva čtení a zápisu, stejné jako u funkce open s FIFO se pracuje jako s obyčejným souborem, tj. open, read, write, close (low-level I/O) nebo fopen, fread, fwrite, fclose (I/O C knihovny) vrací 0, při chybě -1 Z FIFO může číst nebo do ní zapisovat více procesů. Data z každého zapisujícího procesu jsou zapisována atomicky. Další funkce týkající se rour nebo FIFO jsou: Linux - Synchronizace (Synchronization) Programování vláken není jednoduché. Není způsob, jak předem zjistit, kdy systém spustí jedno vlákno a kdy druhé. Debugování vícevláknového programu je těžké, protože nelze vždy reprodukovat chybné chování. Většina problémů je způsobena tím, že vlákna přistupují ke stejným datům. Na jednu stranu je to velká výhoda vláken, ale na druhou stranu to může být nebezpečné. Když je jedno vlákno v půli cesty při zapisování (čtení) dat a druhé je čte (zapisuje), pravděpodobně vznikne chyba. Často program funguje jen pokud vlákno běží dříve nebo později než jiné vlákno. Chyby, které vznikají v důsledku nesprávného pořadí vykonávání vláken, se nazývají race conditions (chyby souběhu), vlákna soutěží o to, které poběží dřív. K eliminování race conditions je potřeba zajistit, aby se vlákna vykonávala ve správném pořadí nebo aby se některé operace prováděly atomicky, tzn. je potřeba vlákna synchronizovat. Atomická operace je nerozdělitelná a nepřerušitelná, když začne, nebude zastavena nebo přerušena, dokud se neukončí. Semafory pro vlákna (Semaphores for threads) Semafor je "počítadlo" umožňující synchronizaci více vláken. Systém zaručuje, že zjištění nebo modifikování hodnoty

16 semaforu je atomická operace. Hodnota semaforu je nezáporné číslo, umožňuje dvě operace: čekání (wait) - sníží hodnotu semaforu o 1. Pokud je hodnota 0, operace je blokována, dokud nebude hodnota kladná. Až bude kladná, sníží se o 1 a čekání končí. nastavení (post) - zvýší hodnotu semaforu o 1. Pokud byla hodnota 0 a nějaká vlákna jsou blokována při čekání na tento semafor, jedno z nich je odblokováno a jeho čekání se ukončí (a hodnota semaforu se vrátí na 0). Semafory pro vlákna jsou implementovány podle standardu POSIX, hlavičkový soubor je <semaphore.h>. sem_init(3) #include <semaphore.h> int sem_init(sem_t *sem, int pshared, unsigned int value); inicializuje semafor, na který ukazuje sem, na hodnotu value pshared specifikuje, zda je semafor lokální pro aktuální proces (0), nebo zda se má sdílet s ostatními procesy (!0), na Linuxu tohle ale není implementováno, musí být vždy 0 vrací 0, při chybě -1 sem_destroy(3) #include <semaphore.h> int sem_destroy(sem_t * sem); zruší semafor, na který ukazuje sem žádné vlákno by na semafor nemělo čekat, jinak chyba vrací 0, při chybě -1 sem_wait(3) #include <semaphore.h> int sem_wait(sem_t * sem); operace wait bod zrušení vlákna vrací vždy 0 sem_trywait(3) #include <semaphore.h> int sem_trywait(sem_t * sem); neblokující operace wait, pokud má semafor hodnotu 0, vrací se s chybou vrací 0, při chybě -1 sem_post(3) #include <semaphore.h> int sem_post(sem_t * sem); operace post nikdy neblokuje a může se bezpečně používat v asynchronních signal-handlerech vrací 0, při chybě -1 sem_getvalue(3) #include <semaphore.h> int sem_getvalue(sem_t * sem, int * sval); uloží aktuální hodnotu semaforu na místo, kam ukazuje sval neměla by se používat k rozhodnutí operace se semaforem, může to vést k race condition: jiné vlákno může změnit hodnotu semaforu mezi touto funkcí a operací vrací vždy 0

17 Př. Napište program, ve kterém vytvoříte vlákno. Jedno vlákno bude něco zapisovat do společného bufferu (naplní ho), druhé z něho číst (vyprázdní ho). Synchronizujte tyto dvě vlákna semafory tak, aby se zapisovalo, jen když je buffer prázdný, a četlo, jen když je plný, a do bufferu v danou chvíli přistupovalo jen jedno vlákno. Semafory pro procesy (Semaphores for processes) Procesy musí koordinovat přístup např. do společné sdílené a mapované paměti. Semafory jsou alokovány, používány a dealokovány stejně jako úseky sdílené paměti, jsou také součástí systémových volání původního unixového systému System V IPC (poslední jsou fronty zpráv). I když ve většině případů stačí jeden semafor, semafory pro procesy existují po množinách. semget(2) #include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> int semget ( key_t key, int nsems, int semflg ) vytvoří množinu nsems semaforů ke klíči key, pokud v key je IPC_PRIVATE, nebo pokud ke klíči key již neexistuje množina semaforů a v semflg je IPC_CREAT v semflg může být: IPC_CREAT - vytvoří novou množinu semaforů, pokud toto není, najde se množina asociovaná ke klíči key IPC_EXCL - používá se s IPC_CREAT, chyba pokud množina semaforů s klíčem key existuje práva přístupu - definovaná v <sys/stat.h>, může být: S_IRUSR, S_IWUSR - čtení, změna pro vlastníka množiny semaforů S_IROTH, S_IWOTH - pro ostatní nsems může být 0, pak se nic nevytvoří, nebo kladné číslo udávající počet semaforů v množině vrací identifikátor množiny semaforů, jinak -1 existuje limit počtu semaforů v množině, viz man Semafory existují i když skončí všechny procesy, které je používají. Proces, který semafory vytvořil, je také musí dealokovat, jinak systému dojdou. Kromě alokace je potřeba semafory také inicializovat. semctl(2) #include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> int semctl (int semid, int semnum, int cmd, union semun arg) zjistí informace o množině semaforů (identifikované pomocí semid) nebo o jednom semaforu, mění její práva, dealokuje ji a inicializuje ji strukturu semun si většinou musíme deklarovat sami, viz man cmd může být: IPC_STAT - vrací informace do semid_ds struktury arg.buf, viz man, potřebuje právo čtení IPC_SET - nastavuje práva IPC_RMID - ihned zruší množinu semaforů (a odblokuje všechny čekající procesy), může jen ten (uživatel), který ji vytvořil nebo vlastník (nebo root) GETALL - vrátí hodnotu všech semaforů do arg.array GETVAL - vrátí hodnotu semnum-tého semaforu (první je 0-tý) SETALL - nastaví hodnoty všech semaforů podle arg.array, čekající procesy jsou odblokovány SETVAL - nastaví hodnotu semnum-tého semaforu na arg.val, čekající procesy jsou odblokovány při chybě vrací -1, jinak záleží na cmd, při GETVAL vrací hodnotu semaforu Každý semafor má nezápornou hodnotu a podporuje operace wait a post. Tyto operace se provádějí pomocí funkce semop. semop(2) #include <sys/types.h> #include <sys/ipc.h>

18 #include <sys/sem.h> int semop ( int semid, struct sembuf *sops, unsigned nsops ) provede operaci na vybraných semaforech (počtu nsops) z množiny semid, operace se provedou jen pokud se všechny provedou úspěšně prvky pole sops specifikují operaci pomocí struktury sembuf, která má prvky: sem_num - číslo ovlivňovaného semaforu, pro první je 0 sem_flg - když je zde SEM_UNDO, při ukončení procesu je semafor vrácen na svou předchozí hodnotu, platí pro všechna volání této funkce během existence procesu, sem_undo struktury procesu se nedědí při fork, ale při exec ano sem_op - operace, může být: kladné číslo - přidá se k hodnotě semaforu, při 1 je to operace post nula - blokuje proces, dokud hodnota semaforu není 0 nebo množina semaforů není zrušena nebo proces nedostane signál, který se obslouží záporné číslo - pokud je hodnota semaforu větší nebo rovna absolutní hodnotě tohoto čísla, je tato absolutní hodnota odečtena od hodnoty semaforu, jinak je proces blokován, dokud hodnota semaforu nebude větší nebo rovna absolutní hodnotě nebo nebo množina semaforů není zrušena nebo proces nedostane signál, který se obslouží, při -1 je to operace wait vrací 0, při chybě -1 Př. Synchronizujte rodiče a potomka v programu ze cvičení 'Linux - Meziprocesní komunikace', část 'Sdílená paměť'. Použijte jeden binární semafor tak, aby proces četl, až tam druhý něco zapíše. ipcs(8) ipcs -s vypíše pole semaforů a informace o nich Př. Podívejte se, zda v systému nezůstaly nepoužívané množiny semaforů. ipcrm(8) ipcrm sem id... zruší množinu semaforů specifikovanou pomocí id Př. Zrušte nepoužívané množiny semaforů. PŘÍKLAD Další funkce týkající se semaforů jsou: Linux - Synchronizace (Synchronization) Mutexy (Mutexes) Řešením většiny race conditions problémů je dovolit v daném čase přístup ke sdíleným datům pouze jednomu vláknu. Když jedno vlákno data mění, žádné jiné by k nim nemělo přistupovat, dokud změna dat neskončí. Mutex (MUTual EXclusion lock) je speciální zámek, který může v daném čase zamčít pouze jedno vlákno. Když se druhé vlákno pokusí zamčít již zamčený mutex, je blokováno, dokud první vlákno mutex neodemče. pthread_mutex_init(3) int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr); inicializuje mutex na ukazateli mutex, nastaví atributy podle mutexattr, pokud je NULL, atributy jsou defaultní, viz pthread_mutexattr_init proměnná typu pthread_mutex_t může být inicializována také staticky pomocí konstanty PTHREAD_MUTEX_INITIALIZER, např. pro globální a statické proměnné

19 vždy vrací 0 pthread_mutex_destroy(3) int pthread_mutex_destroy(pthread_mutex_t *mutex); zruší mutex, který musí být odemčený, uvolní prostředky systému (v Linuxu nejsou mutexům přiděleny žádné prostředky, tzn. funkce se nemusí používat pro zrušení mutexu) vrací 0, při chybě nenulové číslo pthread_mutex_lock(3) int pthread_mutex_lock(pthread_mutex_t *mutex); zamče mutex, pokud je již zamčený, blokuje vlákno, dokud není odemčen vrací 0, při chybě nenulové číslo pthread_mutex_trylock(3) int pthread_mutex_trylock(pthread_mutex_t *mutex); zamče mutex, pokud je již zamčený, vrací chybu vrací 0, při chybě nenulové číslo pthread_mutex_unlock(3) int pthread_mutex_unlock(pthread_mutex_t *mutex); odemče mutex a jedno (náhodné) z blokovaných vláken je odblokováno mutex musí být uzamčený stejným vláknem, ze kterého je volána tato funkce vrací 0, při chybě nenulové číslo Před přístupem (čtení i zápis) ke sdíleným datům si každé vlákno uzamče mutex. Až po dokončení operace s daty mutex odemče. Př. Nahraďte patřičné semafory z příkladu ze cvičení 'Linux - Synchronizace', část 'Semafory pro vlákna', mutexy. Blokování vláken mutexem může způsobit deadlock, který vznikne, když vlákna čekají na něco, co se nikdy nestane. Např. když se vlákno pokusí uzamčít jím zamčený mutex, ale to záleží na typu mutexu: fast mutex - pokus o uzamčení zamčeného mutexu blokuje, dokud není odemčen, inicializační konstanta je PTHREAD_MUTEX_INITIALIZER, defaultní recursive mutex - může být uzamčen vícekrát, uzamčení stejným vláknem se počítá, až stejný počet odemčení (tím vláknem) jej odemče, inicializační konstanta je PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP error-checking mutex - při pokusu o uzamčení již zamčeného mutexu se vrátí chyba, ale neblokuje se, inicializační konstanta je PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP pthread_mutexattr_init(3) int pthread_mutexattr_init(pthread_mutexattr_t *attr); inicializuje atributy mutexu attr a naplní je defaultními hodnotami vrací vždy 0 pthread_mutexattr_setkind_np(3) int pthread_mutexattr_setkind_np(pthread_mutexattr_t *attr, int kind);

20 nastaví typ mutexu v atributech attr na hodnotu kind kind může být PTHREAD_MUTEX_FAST_NP, PTHREAD_MUTEX_RECURSIVE_NP nebo PTHREAD_MUTEX_ERRORCHECK_NP, NP znamená nonportable, tj. nepřenosné rozšíření POSIX standardu vrací 0, při chybě nenulové číslo pthread_mutexattr_getkind_np(3) int pthread_mutexattr_getkind_np(const pthread_mutexattr_t *attr, int *kind); vrátí typ mutexu v atributech attr na adresu kind vrací vždy 0 pthread_mutexattr_destroy(3) int pthread_mutexattr_destroy(pthread_mutexattr_t *attr); zruší atributy mutexu, před novým použitím se musí znovu inicializovat vrací vždy 0 Condition variables Condition variable je třetí synchronizační prostředek v Linuxu, který umožňuje implementovat složitější podmínky běhu více vláken. Například funkce vlákna, která vykonává nekonečnou smyčku. Pokud je nastavena určitá vlajka, vykoná se při iteraci nějaká činnost. void* thread_function(void* thread_arg) { while (1) { int flag_is_set; pthread_mutex_lock(&thread_flag_mutex); flag_is_set = thread_flag; pthread_mutex_unlock(&thread_flag_mutex); } if (flag_is_set) do_work (); } return NULL; void set_thread_flag(int flag_value) { pthread_mutex_lock(&thread_flag_mutex); thread_flag = flag_value; pthread_mutex_unlock(&thread_flag_mutex); } Tohle je správně, ale ne dostatečně. Pokud není vlajka nastavena, spotřebuje se spousta času CPU testováním vlajky a zamykáním a odemykáním mutexu. Je potřeba vlákno uspat, dokud se nestane něco, co nastaví vlajku. Condition variable implementuje podmínku, při které vlákno poběží a naopak podmínku, při které bude vlákno blokováno. Pokud vlákno čeká na condition variable, je blokováno, dokud jiné vlákno nesignalizuje condition variable. Condition variable (na rozdíl od semaforu) není čítač, vlákno na ni musí čekat před tím, než je signalizována. Jinak je signál ztracen a vlákno čeká na další. Zpět k příkladu, pokud není vlajka nastavena, vlákno bude čekat na condition variable. Po nastavení vlajky se condition

21 variable signalizuje a blokované vlákno otestuje vlajku znovu (úspěšně). Je tu ale jeden problém: race condition mezi testováním vlajky a čekáním na condition variable. Např. vlákno zjistí, že vlajka není nastavena. Plánovač přepne vlákna, vlajka se nastaví a signalizuje se condition variable. Signál je ztracen, plánovač přepne vlákno zpět a to začne čekat na condition variable, které se možná nedočká. Potřebujeme zamčít mutexem vlajku i condition variable. Každá condition variable proto musí být použita spolu s mutexem: vlákno zamče mutex a otestuje vlajku pokud je vlajka nastavena, odemče mutex a vykoná činnost pokud ne, atomicky odemče mutex a čeká na condition variable pthread_cond_init(3) int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr); inicializuje condition variable na ukazateli cond, atributy cond_attr nejsou v Linuxu implementovány, tzn. zadává se NULL proměnná typu pthread_cond_t může být inicializována také staticky pomocí konstanty PTHREAD_COND_INITIALIZER, např. pro globální a statické proměnné vždy 0, při chybě nenulové číslo pthread_cond_destroy(3) int pthread_cond_destroy(pthread_cond_t *cond); zruší condition variable, na kterou nesmí žádné vlákno čekat, uvolní prostředky systému (v Linuxu nejsou mutexům přiděleny žádné prostředky, tzn. funkce se nemusí používat pro zrušení condition variable) vrací 0, při chybě nenulové číslo pthread_cond_signal(3) pthread_cond_broadcast(3) int pthread_cond_signal(pthread_cond_t *cond); int pthread_cond_broadcast(pthread_cond_t *cond); signalizuje condition variable, odblokuje nejvýše jedno (náhodné) blokované vlákno nebo všechna blokovaná vlákna (pthread_cond_broadcast) vrací 0, při chybě nenulové číslo pthread_cond_wait(3) int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex); atomicky odemče mutex a čeká na condition variable, mutex musí být zamčený při signalizování znovu zamče mutex ještě před odblokováním vlákna je to bod zrušení vlákna, před zrušením zamče mutex vrací 0, při chybě nenulové číslo Při změně podmínky (vlajky), která je chráněna pomocí condition variable, se musí postupovat takto: zamče se mutex pro condition variable změní se podmínka (vlajka) signalizuje se condition variable odemče se mutex Př. Opravte předložený příklad tak, aby se použila condition variable. Condition variable se může použít i bez podmínky, jednoduše pro blokování vlákna, dokud ho jiné "neprobudí". OTÁZKA: Pro tohle se dá použít i semafor. Jaké jsou principiální rozdíly mezi condition variable a semaforem? Další funkce týkající se mutexů nebo condition variables jsou:

22 Windows - Procesy (Processes) Aplikace pro Windows se skládá z jednoho nebo více procesů. Proces je jednoduše řečeno spuštěný program. Každý proces poskytuje zdroje nutné k vykonávání programu. Proces má vituální adresový prostor, kód, data, proměnné prostředí, prioritu, atd. #include <windows.h> - pro všechny funkce Win32 API Vytvoření procesu CreateProcess vytvoří nový proces jako potomka rodičovského procesu, oba běží nezávisle na sobě vrátí strukturu PROCESS_INFORMATION informací o novém procesu do lpprocessinformation, např. handle (který je platný dokud se neuzavře, tedy i po ukončení procesu) vrací nenulovou hodnotu, při chybě 0 vlastnosti nového procesu lze nastavit pomocí struktury STARTUPINFO: pro GUI procesy: výšku, šířku a pozici okna, které se použijí jako defaultní hodnoty funkce CreateWindow, ncmdshow parametr pro funkci ShowWindow pro konzolové procesy velikost okna a bufferu (ve znacích), pozici, barvy textu a pozadí, titulek konzole lpcommandline - příkazový řádek, tj. jméno programu s parametry binherithandles - jestli potomek zdědí handly dwcreationflags - další nastavení, např. CREATE_NEW_CONSOLE - potomek na novou konzoli, nemůže se používat s DETACHED_PROCESS DETACHED_PROCESS - pro konzolové procesy je bez konzole rodiče, nemůže se používat s CREATE_NEW_CONSOLE CREATE_SUSPENDED - hlavní vlákno procesu se vytvoří pozastavené priorita - defaultní NORMAL_PRIORITY_CLASS, pokud má rodič IDLE_PRIORITY_CLASS, tak tato lpstartupinfo - STARTUPINFO struktura lpprocessinformation - PROCESS_INFORMATION struktura PŘÍKLAD Př. Napište program a spusťte z něj nový konzolový proces s prioritou IDLE_PRIORITY_CLASS. CreateProcessAsUser vytvoří nový proces, který poběží pod jiným uživatelem, specifikovaným pomocí htoken GetCurrentProcessId vrací pid procesu Př. Vypište pid procesu. OpenProcess vrací handle procesu na základě pid, při chybě NULL binherithandle - jestli může být handle děděn dwprocessid - id procesu GetCurrentProcess vrací pseudo handle procesu, který je použitelný jen v rámci tohoto procesu!, lze jej "zveřejnit" na normální handle pomocí DuplicateHandle Př. Zjistěte handle, pseudo handle a "zveřejněný" pseudo handle procesu a porovnejte je s handlem z PROCESS_INFORMATION

23 Informace o procesu GetStartupInfo vrací STARTUPINFO strukturu, použitou při vytvoření procesu, do lpstartupinfo Nový proces může od rodiče zdědit různé vlastnosti a zdroje, a rodičovský proces může určit, co se může zdědit. Potomek může dědit: nedědí: handly otevřených souborů, bufferů, rour, procesů, vláken, mutexů, semaforů, mapování souborů proměnné prostředí aktuální adresář konzoli, pokud rodič není bez konzole nebo pokud si potomek nevytvoří novou pseudo handly prioritu GDI nebo USER handly, např. HBITMAP nebo HMENU Aby se handl zdědil, musí se zděditelnost specifikovat při jeho vytváření, otevírání nebo duplikování a při volání funkce CreateProcess s parametrem finherithandles. Zděděný handl je stejný jako původní, změna na jednom se projeví i na druhém. Ukončení procesu ExitProcess ukončí tento proces s návratovým kódem uexitcode TerminateProcess ukončí jiný proces, jehož handle je hprocess, s návratovým kódem uexitcode vrací nenulovou hodnotu, při chybě 0 Proces se též ukončí, když skončí jeho hlavní nebo poslední vlákno. Handly otevřených souborů a jiné jsou při ukončení procesu uzavřeny, ale stále existují, pokud je používají i jiné procesy. Konzolové procesy lze také ukončit pomocí C-C nebo C-Break. GetExitCodeProcess vrací status ukončení procesu, jehož handle je hprocess, do lpexitcode, je STILL_ACTIVE, pokud proces ještě běží, nebo je to návratový kód procesu, který vrací main nebo WinMain funkce vrací nenulovou hodnotu, při chybě 0 Př. Vypište v rodiči návratový kód potomka. TerminateProcess neukončuje korektně vlákna, pro ukončení procesu jiným by se mělo postupovat takto: oba procesy si zaregistrují privátní zprávu pomocí RegisterWindowMessage jeden ukončí druhého posláním této privátní zprávy pomocí BroadcastSystemMessage, př. BroadcastSystemMessage( BSF_IGNORECURRENTTASK, // do not send message to this process BSM_APPLICATIONS, // broadcast only to applications private message, // message registered in functionvious step wparam, // message-specific value lparam ); // message-specific value proces, co přijme zprávu, se ukončí pomocí ExitProcess Při ukončení procesu se neukončují jeho potomci. Další funkce týkající se procesů jsou:

Operační systémy. Cvičení 5: Volání jádra, procesy, vlákna.

Operační systémy. Cvičení 5: Volání jádra, procesy, vlákna. Operační systémy Cvičení 5: Volání jádra, procesy, vlákna. 1 Obsah cvičení Systémová volání Knihovní funkce jazyka C Procesy informace o procesech vytváření, ukončování procesů, signály POSIX vlákna vytváření,

Více

Linux a vlákna - Linuxové noviny 8-9/1998. Linuxové noviny 08-09/98

Linux a vlákna - Linuxové noviny 8-9/1998. Linuxové noviny 08-09/98 Page 1 of 9 - předchozí článek - následující článek - obsah - úvodní stránka - Linuxové noviny 08-09/98 Linux a vlákna Vladimír Michl, 7. srpna 1998 Tento článek si klade za úkol seznámit čtenáře s vlákny

Více

Práce s pamětí. Tématicky zaměřený vývoj aplikací v jazyce C skupina Systémové programování Linux. Martin Husák, Petr Velan, Martin Drašar

Práce s pamětí. Tématicky zaměřený vývoj aplikací v jazyce C skupina Systémové programování Linux. Martin Husák, Petr Velan, Martin Drašar Práce s pamětí Tématicky zaměřený vývoj aplikací v jazyce C skupina Systémové programování Linux Martin Husák, Petr Velan, Martin Drašar Fakulta informatiky Masarykova univerzita {husakm velan drasar}@ics.muni.cz

Více

OS Procesy a vlákna. Tomáš Hudec. Tomas.Hudec@upce.cz. http://asuei01.upceucebny.cz/usr/hudec/vyuka/os/

OS Procesy a vlákna. Tomáš Hudec. Tomas.Hudec@upce.cz. http://asuei01.upceucebny.cz/usr/hudec/vyuka/os/ OS Procesy a vlákna Tomáš Hudec Tomas.Hudec@upce.cz http://asuei01.upceucebny.cz/usr/hudec/vyuka/os/ Osnova procesy příkazy pro procesy procesy systémová volání signály signály systémová volání vlákna

Více

Meziprocesová komunikace

Meziprocesová komunikace Meziprocesová komunikace mnohé aplikace sestávají z mnoha navzájem spolupracujících procesů, které mezi sebou komunikují a sdílejí informace jádro musí poskytovat mechanizmy, které toto umožní nazýváme

Více

Vlákno odlehčený proces kód vlákna, zásobník privátní ostatní sdíleno s dalšími vlákny téhož procesu

Vlákno odlehčený proces kód vlákna, zásobník privátní ostatní sdíleno s dalšími vlákny téhož procesu Procesy, vlákna Vlákno odlehčený proces kód vlákna, zásobník privátní ostatní sdíleno s dalšími vlákny téhož procesu Implementace vláken one-to-one o implementace na úrovni jádra o každé vlákno je pro

Více

Programování v OS Linux

Programování v OS Linux Programování v OS Linux Argumenty programu Synchronizace vláken 1. Mutexy 2. Semafory vláken 3. Signály ve vláknech Komunikace mezi procesy (IPC) 0. Pomocí argumentů příkazového řádku 1. Signály 2. Semafory

Více

Procesy a vlákna Mgr. Josef Horálek

Procesy a vlákna Mgr. Josef Horálek Procesy a vlákna Mgr. Josef Horálek Procesy a vlákna = Základním úkolem jádra je = Správa běžících procesů a vláken: = vytváření = plánování = nastavování = ukončování Proces, vlákno, úloha = Proces běžící

Více

ZOS 9. cvičení, ukázky kódu. Pavel Bžoch

ZOS 9. cvičení, ukázky kódu. Pavel Bžoch ZOS 9. cvičení, ukázky kódu Pavel Bžoch Obsah Komunikace mezi procesy Atomické operace TSL a CAS Zámky Semafory Semafory vypsání věty Monitor Bariéra pomocí monitoru Implementace semaforu pomocí monitoru

Více

Procesy a vlákna - synchronizace

Procesy a vlákna - synchronizace ÚVOD DO OPERAČNÍCH SYSTÉMŮ Ver.1.00 Procesy a vlákna - synchronizace České vysoké učení technické Fakulta elektrotechnická 2010 Studijní materiály a informace o předmětu http://measure.feld.cvut.cz/vyuka/predmety/bakalarske/navody

Více

Linux Teorie operačních systémů a realita

Linux Teorie operačních systémů a realita ÚVOD DO OPERAČNÍCH SYSTÉMŮ Linux Teorie operačních systémů a realita České vysoké učení technické Fakulta elektrotechnická Ver.1.00 2010 Historie Unixu a Linuxu MULTICS 50. - 60. léta minulého století,

Více

X36UNX. UNIX - signály. jejich význam a použití. Martin Plicka -

X36UNX. UNIX - signály. jejich význam a použití. Martin Plicka - X36UNX UNIX - signály jejich význam a použití Martin Plicka - plickm1@fel.cvut.cz Co jsou signály? Softwarová přerušení zaslaná procesu jiným procesem, terminal driverem, jádrem Druhy signálů jsou očíslovány

Více

Přednáška 6. Procesy a vlákna (vznik, stavy, atributy). Signály. Nástroje pro práci s procesy a vlákny. Úvod do Operačních Systémů Přednáška 6

Přednáška 6. Procesy a vlákna (vznik, stavy, atributy). Signály. Nástroje pro práci s procesy a vlákny. Úvod do Operačních Systémů Přednáška 6 Přednáška 6 Procesy a vlákna (vznik, stavy, atributy). Signály. Nástroje pro práci s procesy a vlákny. 1 Procesy I Proces je spuštěný program. Každý proces má v rámci systému přiřazeno jednoznačné číslo

Více

Výpočet v módu jádro. - přerušení (od zařízení asynchronně) - výjimky - softvérové přerušení. v důsledku událostí

Výpočet v módu jádro. - přerušení (od zařízení asynchronně) - výjimky - softvérové přerušení. v důsledku událostí Výpočet v módu jádro v důsledku událostí - přerušení (od zařízení asynchronně) - výjimky - softvérové přerušení řízení se předá na proceduru pro ošetření odpovídající události část stavu přerušeného procesu

Více

Roury a zprávy Mgr. Josef Horálek

Roury a zprávy Mgr. Josef Horálek Roury a zprávy Mgr. Josef Horálek Roury a zprávy = Jde o metodu místní komunikace mezi procesy. = Jedná se o: = Anonymní roury = Pojmenované roury = Komunikace pomocí zpráv Anonymní roury (pipe) = Nejjednodušší

Více

Procesy a vlákna (Processes and Threads)

Procesy a vlákna (Processes and Threads) ÚVOD DO OPERAČNÍCH SYSTÉMŮ Ver.1.00 Procesy a vlákna (Processes and Threads) Správa procesů a vláken České vysoké učení technické Fakulta elektrotechnická 2012 Použitá literatura [1] Stallings, W.: Operating

Více

Konstruktory a destruktory

Konstruktory a destruktory Konstruktory a destruktory Nedostatek atributy po vytvoření objektu nejsou automaticky inicializovány hodnota atributů je náhodná vytvoření metody pro inicializaci, kterou musí programátor explicitně zavolat,

Více

Management procesu I Mgr. Josef Horálek

Management procesu I Mgr. Josef Horálek Management procesu I Mgr. Josef Horálek Procesy = Starší počítače umožňovaly spouštět pouze jeden program. Tento program plně využíval OS i všechny systémové zdroje. Současné počítače umožňují běh více

Více

Práce se soubory. Základy programování 2 Tomáš Kühr

Práce se soubory. Základy programování 2 Tomáš Kühr Práce se soubory Základy programování 2 Tomáš Kühr Soubory z pohledu C Soubor zjednodušeně chápeme jako posloupnost bytů uložených někde na disku Datový proud (anglicky stream) Ještě obecnější přístup

Více

Práce s binárními soubory. Základy programování 2 Tomáš Kühr

Práce s binárními soubory. Základy programování 2 Tomáš Kühr Práce s binárními soubory Základy programování 2 Tomáš Kühr Binární soubory Mohou mít libovolnou strukturu Data jsou uložena ve stejné podobě jako v paměti za běhu programu Výhody: Pro uložení je potřeba

Více

Řada programovacích jazyků nabízí prostředky pro řešení meziprocesové komunikace jako je synchronizace a řízení přístupu do kritické sekce.

Řada programovacích jazyků nabízí prostředky pro řešení meziprocesové komunikace jako je synchronizace a řízení přístupu do kritické sekce. Operační systémy Tomáš Hudec 7 Prostředky programovacích jazyků pro IPC Obsah: 7.1 Monitor, 7.1.1 Použití monitoru pro řízení přístupu do kritické sekce, 7.1.2 Použití monitoru pro synchronizaci, 7.1.3

Více

Práce se soubory. Úvod do programování 2 Tomáš Kühr

Práce se soubory. Úvod do programování 2 Tomáš Kühr Práce se soubory Úvod do programování 2 Tomáš Kühr Soubory z pohledu C u Soubor chápeme jako posloupnost bytů uložených na disku u Datový proud (anglicky stream) u Ještě obecnější přístup u Sjednocuje

Více

PROGRAMOVÁNÍ V C++ CVIČENÍ

PROGRAMOVÁNÍ V C++ CVIČENÍ PROGRAMOVÁNÍ V C++ CVIČENÍ INFORMACE Michal Brabec http://www.ksi.mff.cuni.cz/ http://www.ksi.mff.cuni.cz/~brabec/ brabec@ksi.mff.cuni.cz gmichal.brabec@gmail.com PODMÍNKY ZÁPOČTU Základní podmínky společné

Více

Operační systémy. Přednáška 2: Procesy a vlákna

Operační systémy. Přednáška 2: Procesy a vlákna Operační systémy Přednáška 2: Procesy a vlákna 1 Procesy Všechen běžící software v systému je organizován jako množina sekvenčně běžících procesů. (Sekvenční) proces Abstrakce běžícího programu. Sekvence

Více

1. lekce. do souboru main.c uložíme následující kód a pomocí F9 ho zkompilujeme a spustíme:

1. lekce. do souboru main.c uložíme následující kód a pomocí F9 ho zkompilujeme a spustíme: 1. lekce 1. Minimální program do souboru main.c uložíme následující kód a pomocí F9 ho zkompilujeme a spustíme: #include #include int main() { printf("hello world!\n"); return 0; 2.

Více

PB071 Programování v jazyce C

PB071 Programování v jazyce C Programování v jazyce C POSIX Organizační Zápočtový příklad nanečisto v tomto týdnu na cvičeních, 60 minut (naostro proběhne 5-11.5., čtvrtkové odpadnuté cvičení 15.5.) Pro účast na zkoušce je nutné mít

Více

Paralelní programování

Paralelní programování Paralelní programování přednášky Jan Outrata únor duben 2011 Jan Outrata (KI UP) Paralelní programování únor duben 2011 1 / 16 Semafory Await synchronizace používající await běží na železe = využívají

Více

Práce se soubory. Úvod do programování 2 Tomáš Kühr

Práce se soubory. Úvod do programování 2 Tomáš Kühr Práce se soubory Úvod do programování 2 Tomáš Kühr Soubory z pohledu C Soubor zjednodušeně chápeme jako posloupnost bytů uložených někde na disku Datový proud (anglicky stream) Ještě obecnější přístup

Více

C++ 0x aka C++11. Základním kamenem je třída std::thread

C++ 0x aka C++11. Základním kamenem je třída std::thread C++ 0x aka C++11 Jako jiné jazyky, např. Free/Object Pascal, se C++ ve standardu ++0x dočkal podpory vláken Výhodou je, že standardní knihovna je platformě nezávislá na úrovni zdrojového kódu Základním

Více

Pár odpovědí jsem nenašla nikde, a tak jsem je logicky odvodila, a nebo jsem ponechala odpověď z pefky, proto je možné, že někde bude chyba.

Pár odpovědí jsem nenašla nikde, a tak jsem je logicky odvodila, a nebo jsem ponechala odpověď z pefky, proto je možné, že někde bude chyba. Odpovědi jsem hledala v prezentacích a na http://www.nuc.elf.stuba.sk/lit/ldp/index.htm Pár odpovědí jsem nenašla nikde, a tak jsem je logicky odvodila, a nebo jsem ponechala odpověď z pefky, proto je

Více

1. lekce. do souboru main.c uložíme následující kód a pomocí F9 ho zkompilujeme a spustíme:

1. lekce. do souboru main.c uložíme následující kód a pomocí F9 ho zkompilujeme a spustíme: 1. lekce 1. Minimální program do souboru main.c uložíme následující kód a pomocí F9 ho zkompilujeme a spustíme: #include #include int main() { printf("hello world!\n"); return 0; 2.

Více

Operační systémy 2: Zápočtové úkoly

Operační systémy 2: Zápočtové úkoly Operační systémy 2: Zápočtové úkoly 18. listopad 2010 1 Paralelní Mergesort Implementujte paralelní verzi algoritmu Merge sort, který bude řadit celá čísla uložená v textovém souboru. Program bude mít

Více

Vlákna a přístup ke sdílené paměti. B4B36PDV Paralelní a distribuované výpočty

Vlákna a přístup ke sdílené paměti. B4B36PDV Paralelní a distribuované výpočty Vlákna a přístup ke sdílené paměti B4B36PDV Paralelní a distribuované výpočty Minulé cvičení: Paralelizace nám může pomoct... 1 Minulé cvičení: Paralelizace nám může pomoct... B4B36PDV: Ale ne všechny

Více

Principy operačních systémů. Lekce 6: Synchronizace procesů

Principy operačních systémů. Lekce 6: Synchronizace procesů Principy operačních systémů Lekce 6: Synchronizace procesů Kritická sekce Při multitaskingu (multithreadingu) různé procesy často pracují nad společnou datovou strukturou (např. zápis a čtení do/z fronty)

Více

Systém souborů (file system, FS)

Systém souborů (file system, FS) UNIX systém souborů (file system) 1 Systém souborů (file system, FS)! slouží k uchování dat na vnějším paměťovém médiu a zajišťuje přístup ke struktuře dat! pro uživatele možnost ukládat data a opět je

Více

OS Konkurence procesů a IPC

OS Konkurence procesů a IPC OS Konkurence procesů a IPC Tomáš Hudec Tomas.Hudec@upce.cz http://asuei01.upceucebny.cz/usr/hudec/vyuka/os/ Tomáš Hudec OS: Konkurence procesů a IPC 2 / 133 Konkurence procesů (vláken) a problémy současného

Více

Operační systémy Tomáš Hudec. 6 Komunikace procesů (IPC) Obsah: 6.1 Klasické problémy souběhu. 6.1.1 Obědvající filosofové

Operační systémy Tomáš Hudec. 6 Komunikace procesů (IPC) Obsah: 6.1 Klasické problémy souběhu. 6.1.1 Obědvající filosofové Operační systémy Tomáš Hudec 6 Komunikace procesů (IPC) Obsah: 6.1 Klasické problémy souběhu, 6.1.1 Obědvající filosofové, 6.1.2 Producenti a konzumenti, 6.1.3 Problém spících holičů, 6.1.4 Problém pisatelů

Více

for (i = 0, j = 5; i < 10; i++) { // tělo cyklu }

for (i = 0, j = 5; i < 10; i++) { // tělo cyklu } 5. Operátor čárka, - slouží k jistému určení pořadí vykonání dvou příkazů - oddělím-li čárkou dva příkazy, je jisté, že ten první bude vykonán dříve než příkaz druhý. Např.: i = 5; j = 8; - po překladu

Více

Přednáška 2. Systémy souborů OS UNIX. Nástroje pro práci se souborovým systémem. Úvod do Operačních Systémů Přednáška 2

Přednáška 2. Systémy souborů OS UNIX. Nástroje pro práci se souborovým systémem. Úvod do Operačních Systémů Přednáška 2 Přednáška 2 Systémy souborů OS UNIX. Nástroje pro práci se souborovým systémem. 1 Systém souborů (FS) I 2 Systém souborů II Logický systém souborů pro běžného uživatele se jeví jako jediná homogenní struktura

Více

Cvičení č. 3. Sdílené prostředky a synchronizace Program Banka. 4 body

Cvičení č. 3. Sdílené prostředky a synchronizace Program Banka. 4 body Cvičení č. 3 Sdílené prostředky a synchronizace Program Banka 4 body Datum: 12.3.2008 1 Obsah 1. Úvod...2 2. Pokyny pro odevzdání...2 3. Příprava...2 4. Úlohy...3 4.1. Požadavky na program...3 4.2. Požadavky

Více

Operační systémy. Cvičení 3: Programování v C pod Unixem

Operační systémy. Cvičení 3: Programování v C pod Unixem Operační systémy Cvičení 3: Programování v C pod Unixem 1 Obsah cvičení Editace zdrojového kódu Překlad zdrojového kódu Základní datové typy, struktura, ukazatel, pole Načtení vstupních dat Poznámka: uvedené

Více

Pokročilé programování v jazyce C pro chemiky (C3220) Operátory new a delete, virtuální metody

Pokročilé programování v jazyce C pro chemiky (C3220) Operátory new a delete, virtuální metody Pokročilé programování v jazyce C pro chemiky (C3220) Operátory new a delete, virtuální metody Dynamická alokace paměti Jazyky C a C++ poskytují programu možnost vyžádat si část volné operační paměti pro

Více

Téma 3. Procesy a vlákna

Téma 3. Procesy a vlákna Operační systémy a sítě Petr Štěpán, K13133 KN-E-129 stepan@fel.cvut.cz Téma 3. Procesy a vlákna Pojem Výpočetní proces Výpočetní proces (job, task) spuštěný program Proces je identifikovatelný jednoznačné

Více

Paralelní programování

Paralelní programování Paralelní programování cvičení Jan Outrata únor duben 2011 Jan Outrata (KI UP) Paralelní programování únor duben 2011 1 / 13 Cvičení 1 Jazyk C POSIX Threads (UNIX) hlavičkový soubor pthread.h, knihovna

Více

Správné vytvoření a otevření textového souboru pro čtení a zápis představuje

Správné vytvoření a otevření textového souboru pro čtení a zápis představuje f1(&pole[4]); funkci f1 předáváme hodnotu 4. prvku adresu 4. prvku adresu 5. prvku hodnotu 5. prvku symbolická konstanta pro konec souboru je eof EOF FEOF feof Správné vytvoření a otevření textového souboru

Více

8 Třídy, objekty, metody, předávání argumentů metod

8 Třídy, objekty, metody, předávání argumentů metod 8 Třídy, objekty, metody, předávání argumentů metod Studijní cíl Tento studijní blok má za cíl pokračovat v základních prvcích jazyka Java. Konkrétně bude věnována pozornost třídám a objektům, instančním

Více

OS Konkurence procesů a IPC

OS Konkurence procesů a IPC OS Konkurence procesů a IPC Tomáš Hudec Tomas.Hudec@upce.cz http://asuei01.upceucebny.cz/usr/hudec/vyuka/os/ Konkurence procesů sdílení prostředků paměť, CPU, soubory komunikace procesů přístup ke sdílené

Více

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007 Úvod do programovacích jazyků (Java) Michal Krátký Katedra informatiky VŠB Technická univerzita Ostrava Úvod do programovacích jazyků (Java), 2006/2007 c 2006 Michal Krátký Úvod do programovacích jazyků

Více

Úvod do Operačních Systémů

Úvod do Operačních Systémů Úvod do Operačních Systémů 8. cvičení Práce s procesy a úlohami, příkaz test 1 Obsah Práce s procesy ps, ptree, pgrep, time kill, trap nice, stty, truss (strace) vmstat, top Práce s úlohami test nohup,

Více

Operační systémy. Cvičení 4: Programování v C pod Unixem

Operační systémy. Cvičení 4: Programování v C pod Unixem Operační systémy Cvičení 4: Programování v C pod Unixem 1 Obsah cvičení Řídící struktury Funkce Dynamická alokace paměti Ladění programu Kde najít další informace Poznámka: uvedené příklady jsou dostupné

Více

Přednáška. Vstup/Výstup. Katedra počítačových systémů FIT, České vysoké učení technické v Praze Jan Trdlička, 2012

Přednáška. Vstup/Výstup. Katedra počítačových systémů FIT, České vysoké učení technické v Praze Jan Trdlička, 2012 Přednáška Vstup/Výstup. Katedra počítačových systémů FIT, České vysoké učení technické v Praze Jan Trdlička, 2012 Příprava studijního programu Informatika je podporována projektem financovaným z Evropského

Více

ZOS OPAKOVÁNÍ. L. Pešička

ZOS OPAKOVÁNÍ. L. Pešička ZOS OPAKOVÁNÍ L. Pešička ZÁKLADNÍ PRAVIDLO Důležité je znát nejen fakta, ale porozumět jim a zasadit je do kontextu celého OS Př. algoritmus Second Chance využívá bitu Referenced tak, že (fakta) a kdy

Více

Programování v jazyce C pro chemiky (C2160) 4. Textové řetězce, zápis dat do souboru

Programování v jazyce C pro chemiky (C2160) 4. Textové řetězce, zápis dat do souboru Programování v jazyce C pro chemiky (C2160) 4. Textové řetězce, zápis dat do souboru Textové řetězce V jazyce C neexistuje typ proměnné, který by byl určen výhradně pro ukládání textu V jazyce C používáme

Více

Úvod do jazyka C. Ing. Jan Fikejz (KST, FEI) Fakulta elektrotechniky a informatiky Katedra softwarových technologií

Úvod do jazyka C. Ing. Jan Fikejz (KST, FEI) Fakulta elektrotechniky a informatiky Katedra softwarových technologií 1 Fakulta elektrotechniky a informatiky Katedra softwarových technologií 12. října 2009 Organizace výuky Přednášky Teoretické základy dle normy jazyka C Cvičení Praktické úlohy odpřednášené látky Prostřední

Více

Programování v C++, 2. cvičení

Programování v C++, 2. cvičení Programování v C++, 2. cvičení 1 1 Fakulta jaderná a fyzikálně inženýrská České vysoké učení technické v Praze Zimní semestr 2018/2019 Přehled 1 Operátory new a delete 2 3 Operátory new a delete minule

Více

Základy programování (IZP)

Základy programování (IZP) Základy programování (IZP) Páté počítačové cvičení Brno University of Technology, Faculty of Information Technology Božetěchova 1/2, 612 66 Brno - Královo Pole Petr Veigend, iveigend@fit.vutbr.cz 5. týden

Více

Služba ve Windows. Služba (service) je program

Služba ve Windows. Služba (service) je program Služby Windows Autorem materiálu a všech jeho částí, není-li uvedeno jinak, je Ing. Libor Otáhalík. Dostupné z Metodického portálu www.rvp.cz, ISSN: 1802-4785. Provozuje Národní ústav pro vzdělávání, školské

Více

Z. Kotala, P. Toman: Java ( Obsah )

Z. Kotala, P. Toman: Java ( Obsah ) Z. Kotala, P. Toman: Java ( Obsah ) 13. Výjimky Výjimka (exception) je definována jako událost, která nastane během provádění programu a která naruší normální běh instrukcí. Výjimka je vyvolána například

Více

Programování v jazyce C a C++

Programování v jazyce C a C++ Programování v jazyce C a C++ Příklad na tvorbu třídy Richter 1 4. prosince 2017 1 Ing. Richter Miloslav, Ph.D., UAMT FEKT VUT Brno Dvourozměrné pole pomocí tříd Zadání Navrhněte a napište třídu pro realizace

Více

Pavel Procházka. 3. prosince 2014

Pavel Procházka. 3. prosince 2014 Jazyk C# (seminář 11) Pavel Procházka KMI 3. prosince 2014 Motivace Dnes už se prakticky nedělají jednojádrové procesory pokud potřebujeme výkon, musíme zapojit všechna jádra Často potřebujeme dělat více

Více

Více o konstruktorech a destruktorech

Více o konstruktorech a destruktorech Více o konstruktorech a destruktorech Více o konstruktorech a o přiřazení... inicializovat objekt lze i pomocí jiného objektu lze provést přiřazení mezi objekty v původním C nebylo možné provést přiřazení

Více

přetížení operátorů (o)

přetížení operátorů (o) přetížení operátorů (o) - pro vlastní typy je možné přetížit i operátory (tj. definovat vlastní) - pro definici slouží klíčové slovo operator následované typem/znakem operátoru - deklarace pomocí funkčního

Více

Spuštění instalace. nastavení boot z cd v BIOSu vložení CD s instal. médiem spuštění PC. nastavení parametrů instalace (F2 čěština)

Spuštění instalace. nastavení boot z cd v BIOSu vložení CD s instal. médiem spuštění PC. nastavení parametrů instalace (F2 čěština) Instalace OS Linux Autorem materiálu a všech jeho částí, není-li uvedeno jinak, je Ing. Libor Otáhalík. Dostupné z Metodického portálu www.rvp.cz, ISSN: 1802-4785. Provozuje Národní ústav pro vzdělávání,

Více

VISUAL BASIC. Práce se soubory

VISUAL BASIC. Práce se soubory VISUAL BASIC Práce se soubory Práce se soubory 1/2 2 Vstupní data pro programy bývají uloženy do souborů Vstupy pro výpočet, nastavení vzhledu aplikace Výsledky práce programu je potřeba uchovat uložit

Více

Synchronizace Mgr. Josef Horálek

Synchronizace Mgr. Josef Horálek Synchronizace Mgr. Josef Horálek Synchronizace procesu = Kooperující proces je proces, který může ovlivnit nebo být ovlivněn jiným procesem právě spuštěným v systému = Spolupracující procesy mohou sdílet:

Více

8. lekce Úvod do jazyka C 3. část Základní příkazy jazyka C Miroslav Jílek

8. lekce Úvod do jazyka C 3. část Základní příkazy jazyka C Miroslav Jílek 8. lekce Úvod do jazyka C 3. část Základní příkazy jazyka C Miroslav Jílek 1/41 Základní příkazy Všechny příkazy se píšou malými písmeny! Za většinou příkazů musí být středník (;)! 2/41 Základní příkazy

Více

Mělká a hluboká kopie

Mělká a hluboká kopie Karel Müller, Josef Vogel (ČVUT FIT) Mělká a hluboká kopie BI-PA2, 2011, Přednáška 5 1/28 Mělká a hluboká kopie Ing. Josef Vogel, CSc Katedra softwarového inženýrství Katedra teoretické informatiky, Fakulta

Více

ZPRO v "C" Ing. Vít Hanousek. verze 0.3

ZPRO v C Ing. Vít Hanousek. verze 0.3 verze 0.3 Hello World Nejjednoduší program ukazující vypsání textu. #include using namespace std; int main(void) { cout

Více

Předmluva k aktuálnímu vydání Úvod k prvnímu vydání z roku Typografické a syntaktické konvence... 20

Předmluva k aktuálnímu vydání Úvod k prvnímu vydání z roku Typografické a syntaktické konvence... 20 Obsah 5 Obsah Předmluva k aktuálnímu vydání 15 1 Úvod k prvnímu vydání z roku 2000 16 Typografické a syntaktické konvence................ 20 2 Základní pojmy 21 2.1 Trocha historie nikoho nezabije................

Více

7. Datové typy v Javě

7. Datové typy v Javě 7. Datové typy v Javě Primitivní vs. objektové typy Kategorie primitivních typů: integrální, boolean, čísla s pohyblivou řádovou čárkou Pole: deklarace, vytvoření, naplnění, přístup k prvkům, rozsah indexů

Více

Obsah. Kapitola 1 Hardware, procesory a vlákna Prohlídka útrob počítače...20 Motivace pro vícejádrové procesory...21

Obsah. Kapitola 1 Hardware, procesory a vlákna Prohlídka útrob počítače...20 Motivace pro vícejádrové procesory...21 Stručný obsah 1. Hardware, procesory a vlákna... 19 2. Programování s ohledemna výkon... 45 3. Identifikování příležitostí pro paralelizmus... 93 4. Synchronizace a sdílení dat... 123 5. Vlákna v rozhraní

Více

Paralelní programování

Paralelní programování Paralelní programování přednášky Jan Outrata únor duben 2011 Jan Outrata (KI UP) Paralelní programování únor duben 2011 1 / 17 Monitor Semafor vedle aktivní (čekací smyčka, busy-wait) i pasivní implementace

Více

Vláknové programování část VI

Vláknové programování část VI Vláknové programování část VI Lukáš Hejmánek, Petr Holub {xhejtman,hopet}@ics.muni.cz Laboratoř pokročilých síťových technologií PV192 2015 04 14 1/95 Vytváření vláken a procesů v Linuxu Vlákno vzniká

Více

Programování v jazyce C a C++

Programování v jazyce C a C++ Programování v jazyce C a C++ Richter 1 Petyovský 2 1. března 2015 1 Ing. Richter Miloslav, Ph.D., UAMT FEKT VUT Brno 2 Ing. Petyovský Petr, UAMT FEKT VUT Brno C++ Stručná charakteristika Nesdíĺı normu

Více

Algoritmizace a programování

Algoritmizace a programování Algoritmizace a programování Strukturované proměnné Struktura, union Jazyk C České vysoké učení technické Fakulta elektrotechnická A8B14ADP Jazyk C - Strukturované proměnné Ver.1.10 J. Zděnek 20151 Struktura

Více

Vícevláknové programování na CPU: POSIX vlákna a OpenMP I. Šimeček

Vícevláknové programování na CPU: POSIX vlákna a OpenMP I. Šimeček Vícevláknové programování na CPU: POSIX vlákna a OpenMP I. Šimeček xsimecek@fit.cvut.cz Katedra počítačových systémů FIT České vysoké učení technické v Praze Ivan Šimeček, 2011 MI-PRC, LS2010/11, Predn.2

Více

Jazyk C práce se soubory. Jan Hnilica Počítačové modelování 16

Jazyk C práce se soubory. Jan Hnilica Počítačové modelování 16 Jazyk C práce se soubory 1 Soubory Použití souborů pro vstup většího množství dat do programu (uživatel nezadává z klávesnice ručně tisíce údajů...) pro uložení většího množství výsledků, např. k pozdějšímu

Více

Př. další použití pointerů

Př. další použití pointerů Př. další použití pointerů char *p_ch; int *p_i; p_ch = (char *) p_i; // konverze int * na char * 8 int i = 5; int *p_i; p_i = &i; POZOR!!!! scanf("%d", p_i); printf("%d", *p_i); Obecný pointer na cokoliv:

Více

C2110 Operační systém UNIX a základy programování

C2110 Operační systém UNIX a základy programování C2110 Operační systém UNIX a základy programování 6. lekce Petr Kulhánek, Jakub Štěpán kulhanek@chemi.muni.cz Národní centrum pro výzkum biomolekul, Přírodovědecká fakulta Masarykova univerzita, Kotlářská

Více

Operační systémy. Tomáš Vojnar IOS 2009/2010. Vysoké učení technické v Brně Fakulta informačních technologií Božetěchova 2, 612 66 Brno

Operační systémy. Tomáš Vojnar IOS 2009/2010. Vysoké učení technické v Brně Fakulta informačních technologií Božetěchova 2, 612 66 Brno Operační systémy IOS 2009/2010 Tomáš Vojnar Vysoké učení technické v Brně Fakulta informačních technologií Božetěchova 2, 612 66 Brno ÚÓ Ò Ö ØºÚÙØ ÖºÞ Úvod do UNIXu p.1/11 Unix úvod Úvod do UNIXu p.2/11

Více

Implementace LL(1) překladů

Implementace LL(1) překladů Překladače, přednáška č. 6 Ústav informatiky, FPF SU Opava sarka.vavreckova@fpf.slu.cz Poslední aktualizace: 30. října 2007 Postup Programujeme syntaktickou analýzu: 1 Navrhneme vhodnou LL(1) gramatiku

Více

Vláknové programování část I

Vláknové programování část I Vláknové programování část I Lukáš Hejmánek, Petr Holub {xhejtman,hopet}@ics.muni.cz Laboratoř pokročilých síťových technologií PV192 2012 02 21 1/46 For the past thirty years, computer performance has

Více

Připravil: David Procházka. Programovací jazyk C++

Připravil: David Procházka. Programovací jazyk C++ 17. října 2011, Brno Připravil: David Procházka Práce s výjimkami Programovací jazyk C++ Obecně Strana 2 / 21 Jak se může program zachovat při chybě Dříve byl obvyklý způsob zavolat metodu abort. Metoda

Více

TG Motion verze 4 Modul Virtuální PLC návod k obsluze

TG Motion verze 4 Modul Virtuální PLC návod k obsluze TG Motion verze 4 Modul Virtuální PLC návod k obsluze Olomoucká 1290/79-1 - Fax: +420 548 141 890 Historie revizí datum verze popis 10. 1. 2017 1.0 31. 7. 2017 1.1 upravena typografie Olomoucká 1290/79-2

Více

Cvičení č. 5. Programování ve Windows program stopky 3 Body

Cvičení č. 5. Programování ve Windows program stopky 3 Body Cvičení č. 5 Programování ve Windows program stopky 3 Body Datum: 31.3.2008 1 Obsah 1. Úvod...2 2. Pokyny pro odevzdání...2 3. Příprava...2 4. Úlohy...3 4.1. Požadavky na program SleepTest...3 4.2. Požadavky

Více

2 Základní funkce a operátory V této kapitole se seznámíme s použitím funkce printf, probereme základní operátory a uvedeme nejdůležitější funkce.

2 Základní funkce a operátory V této kapitole se seznámíme s použitím funkce printf, probereme základní operátory a uvedeme nejdůležitější funkce. Vážení zákazníci, dovolujeme si Vás upozornit, že na tuto ukázku knihy se vztahují autorská práva, tzv copyright To znamená, že ukázka má sloužit výhradnì pro osobní potøebu potenciálního kupujícího (aby

Více

IUJCE 07/08 Přednáška č. 6

IUJCE 07/08 Přednáška č. 6 Správa paměti Motivace a úvod v C (skoro vždy) ručně statické proměnné o datový typ, počet znám v době překladu o zabírají paměť po celou dobu běhu programu problém velikosti definovaných proměnných jak

Více

PB161 programování v C++ Výjimky Bezpečné programování

PB161 programování v C++ Výjimky Bezpečné programování PB161 programování v C++ Výjimky Bezpečné programování Chyby... Snaha psát programy bez chyb myslet : ) Snaha psát programy se schopností fault tolerance. snaha se z chybového stavu dostat lze řešit testováním

Více

Bitové operátory a bitová pole. Úvod do programování 2 Tomáš Kühr

Bitové operátory a bitová pole. Úvod do programování 2 Tomáš Kühr Bitové operátory a bitová pole Úvod do programování 2 Tomáš Kühr Bitové operátory Provádějí danou operaci s jednotlivými bity svých operandů Operandy bitových operátorů mohou být pouze celočíselné Vyhodnocení

Více

Ukázka zkouškové písemka OSY

Ukázka zkouškové písemka OSY Ukázka zkouškové písemka OSY Jméno a příjmení:.......................................... Odpovězte na otázky zaškrtnutím příslušného políčka. Otázky označené znakem mohou mít více než jednu správnou odpověď.

Více

Lekce 04 Řídící struktury

Lekce 04 Řídící struktury Počítačové laboratoře bez tajemství aneb naučme se učit algoritmizaci a programování s využitím robotů Lekce 04 Řídící struktury Tento projekt CZ.1.07/1.3.12/04.0006 je spolufinancován Evropským sociálním

Více

Knihovna XmlLib TXV 003 63.01 druhé vydání říjen 2012 změny vyhrazeny

Knihovna XmlLib TXV 003 63.01 druhé vydání říjen 2012 změny vyhrazeny Knihovna XmlLib TXV 003 63.01 druhé vydání říjen 2012 změny vyhrazeny 1 TXV 003 63.01 Historie změn Datum Vydání Popis změn Prosinec 2010 1 První vydání, popis odpovídá XmlLib_v13 Říjen 2012 2 Druhé vydání,

Více

Přidělování zdrojů (prostředků)

Přidělování zdrojů (prostředků) Přidělování zdrojů (prostředků) Proces potřebuje zdroje (prostředky) hardware (I/O zařízení, paměť) software (data, programy) Klasifikace zdrojů (z hlediska multitaskingového režimu) Násobně použitelné

Více

10 Práce s řetězci - pokračování

10 Práce s řetězci - pokračování 10 Práce s řetězci - pokračování Máme deklarováno: char retez[50]; - čtení z klávesnice: scanf("%s", retez); - čtení zadané počtu znaků z klávesnice scanf("%10s", retez); // přečti řetězec z klávesnice,max

Více

PREPROCESOR POKRAČOVÁNÍ

PREPROCESOR POKRAČOVÁNÍ PREPROCESOR POKRAČOVÁNÍ Chybová hlášení V C# podobně jako v C++ existuje direktiva #error, která způsobí vypsání chybového hlášení překladačem a zastavení překladu. jazyk C# navíc nabízí direktivu #warning,

Více

Programování v C++ 2, 4. cvičení

Programování v C++ 2, 4. cvičení Programování v C++ 2, 4. cvičení statické atributy a metody, konstruktory 1 1 Fakulta jaderná a fyzikálně inženýrská České vysoké učení technické v Praze Zimní semestr 2018/2019 Přehled Přístupová práva

Více

Vláknové programování část I

Vláknové programování část I Vláknové programování část I Lukáš Hejmánek, Petr Holub {xhejtman,hopet}@ics.muni.cz Laboratoř pokročilých síťových technologií PV192 2015 04 07 1/27 Vláknové programování v C/C++ 1. Procesy, vlákna, přepínání

Více

Základy programování (IZP)

Základy programování (IZP) Základy programování (IZP) Šesté počítačové cvičení Brno University of Technology, Faculty of Information Technology Božetěchova 1/2, 612 66 Brno - Královo Pole Petr Veigend, iveigend@fit.vutbr.cz 6. týden

Více

Struktura programu v době běhu

Struktura programu v době běhu Struktura programu v době běhu Miroslav Beneš Dušan Kolář Struktura programu v době běhu Vztah mezi zdrojovým programem a činností přeloženého programu reprezentace dat správa paměti aktivace podprogramů

Více

IUJCE 07/08 Přednáška č. 4. v paměti neexistuje. v paměti existuje

IUJCE 07/08 Přednáška č. 4. v paměti neexistuje. v paměti existuje Konstanty I možnosti: přednostně v paměti neexistuje žádný ; o preprocesor (deklarace) #define KONSTANTA 10 o konstantní proměnná (definice) const int KONSTANTA = 10; příklad #include v paměti

Více