Programování v OS Linux

Podobné dokumenty
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

Meziprocesová komunikace

OS Procesy a vlákna. Tomáš Hudec. Tomas.Hudec@upce.cz.

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

PB071 Programování v jazyce C

Procesy a vlákna - synchronizace

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

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

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

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

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

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

Základy programování (IZP)

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

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

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

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

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

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

- program = vykonatelný soubor - proces = jedna instance vykonávaného programu

B4B35OSY: Operační systémy

Algoritmizace a programování

Linux - Procesy (Processes)

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.

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

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

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

Dílčí příklady použití jazykových konstrukcí v projektu. Jazyk C Příklady. Pravidla překladu v gmake. Zadání

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

Základní datové struktury

Algoritmizace a programování

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

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

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

Příklad aplikace Klient/Server s Boss/Worker modelem (informativní)

Preprocesor. Karel Richta a kol. katedra počítačů FEL ČVUT v Praze. Karel Richta, Martin Hořeňovský, Aleš Hrabalík, 2016

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

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

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

Příkaz finger. # finger sam Login: sam Name: Sam Greenfield Directory: /home/sam Shell: /bin/tcsh Last login Sun Dec 25 14:47 (EST) on tty2 No Plan.

Struktura programu v době běhu

Motivace. Vstup a výstup. Minimální komunikace. Motivace. ÚDPJ - Vstup a výstup. Ing. Lumír Návrat katedra informatiky, A

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

Cvičení 9 - Monitory. monitor m; var proměnné... procedure p; begin... end; begin inicializace; end;

Procesy a vlákna IPC Komunikace mezi procesy (IPC = Inter-Process Communication)

Obsah přednášky 7. Základy programování (IZAPR) Přednáška 7. Parametry metod. Parametry, argumenty. Parametry metod.

Strukturu lze funkci předat: (pole[i])+j. switch(výraz) velikost ukazatele

Paralelní programování

Paralelní a distribuované výpočty (B4B36PDV)

Procesy a vlákna Mgr. Josef Horálek

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

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

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

vstup a výstupv jazyce C

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

6. lekce Úvod do jazyka C knihovny datové typy, definice proměnných základní struktura programu a jeho editace Miroslav Jílek

Paralelní programování

Opakování programování

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

Semestrální práce z předmětu. Jan Bařtipán / A03043 bartipan@studentes.zcu.cz

Roury a zprávy Mgr. Josef Horálek

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

Stromy, soubory. BI-PA1 Programování a Algoritmizace 1. Ladislav Vagner, Josef Vogel

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

Základy programování (IZP)

Programovací jazyk C(++) C++ area->vm_mm->locked_vm -= len >> PAGE_SHIFT;

Zápis programu v jazyce C#

Obsah. Předmluva 13 Zpětná vazba od čtenářů 14 Zdrojové kódy ke knize 15 Errata 15

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

Paralelní programování

Objektově orientované programování

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

Vstup a výstup datové proudy v C

Vstupní a vstupní proudy v C++

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

PREPROCESOR POKRAČOVÁNÍ

11. Implementace ovladače ve Windows

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

14. Složitější konstrukce

Management procesu I Mgr. Josef Horálek

18. února 2015, Brno Připravil: David Procházka. Programovací jazyk C++

Synchronizace procesů

Základy programování (IZP)

PB071 Programování v jazyce C Jaro 2015

DUM č. 20 v sadě. 29. Inf-5 RoboLab a Lego Mindstorms

PŘETĚŽOVÁNÍ OPERÁTORŮ

Odvozené a strukturované typy dat

Základy programování (IZP)

Synchronizace procesů

Práce s řetězci. IUJCE Přednáška č. 10. string.h. vrací: délku řetězce str (bez '\0')

LabView jako programovací jazyk II

IUJCE Přednáška č. 11. další prvky globální proměnné, řízení viditelnosti proměnných, funkcí

Základy programování (IZP)

Ukázka zkouškové písemka OSY

- tzv. standardní vstupní a výstupní proud (input / output stream)

9. lekce Úvod do jazyka C 4. část Funkce, rekurze Editace, kompilace, spuštění Miroslav Jílek

Od CGI k FastCGI. Uvedené dílo podléhá licenci Creative Commons Uved te autora 3.0 Česko.

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

Řešení sady 1. Úvod do programování 1 Tomáš Kühr

Semafory Zobecněním operací WAKEUP a SLEEP přidáním celočíselného čítače vzniknou semafory a jejich atomické operace DOWN a UP.

Transkript:

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 procesů 3. Sdílená paměť 4. Fronty zpráv 5. Roury 6. Síťová rozhraní (sockets)

Argumenty programu int main( int argc, char *argv[ ], char *envp[ ] ) Argumenty příkazového řádku: argc - počet řetězců v příkazové řádce argv[ ] - pole řetězců reprezentujících jednotlivé argumenty programu envp[ ] - pole řetězců reprezentujících jednotlivé proměnné prostředí!!!pozor!!! některé implementace jazyka C argument *envp[ ] nepodporují V Linuxu se k proměnným prostředím přistupuje pomocí funkcí char *getenv (const char *name); int putenv(const char *string);

/* Program args.c */ #include <stdio.h> #include <process.h> void main( int argc, char *argv[]) { int count; /* Zobrazení jednotlivých argumentů příkazové řádky */ printf( "\ncommand-line arguments:\n" ); for ( count = 0; count < argc; count++ ) { if (argv[count][0] == - ) printf( option: %s\n", argv[count]+1); else printf( argument %d: %s\n", count, argv[count]); exit(0);

$./args -i -lr hello -f fred.c argument 0: args option: i option: lr argument 3: hello option: f argument 5: fred.c

Procesy #include <stdio.h> #include <unistd.h> int main () { printf ( The process ID is %d\n, (int) getpid ()); printf ( The parent process ID is %d\n, (int) getppid ()); return 0;

Procesy system() #include <stdlib.h> int main () { int return_value; return_value = system ( ls -l / ); return return_value;

Procesy fork, exec #include <stdio.h> #include <sys/types.h> #include <unistd.h> int main () { pid_t child_pid; printf ( the main program process ID is %d\n, (int) getpid ()); child_pid = fork (); if (child_pid!= 0) { printf ( this is the parent process, with id %d\n, (int) getpid ()); printf ( the child s process ID is %d\n, (int) child_pid); else printf ( this is the child process, with id %d\n, (int) getpid ()); return 0;

#include <pthread.h> #include <stdio.h> void * print_xs (void* unused) { while (1) fputc ( x, stderr); return NULL; Vlákna - vytvoření int main () { pthread_t thread_id; pthread_create (&thread_id, NULL, &print_xs, NULL); while (1) fputc ( o, stderr); return 0;

Mutexy MUTual EXclusion locks MUTEX zámek, který může uzamknout (zablokovat) v daném časovém okamžiku pouze jediné vlákno; další vlákna musí čekat dokud nebude mutex odblokovaný; odblokování musí provést stejné vlákno, které mutex uzamklo.

Mutexy - pokračování #include <pthread.h> ZÁKLADNÍ FUNKCE PRO PRÁCI S MUTEXY: int pthread_mutex_init (pthread_mutex_t *mutex, pthread_mutex_ attr); //může být NULL int pthread_mutex_lock (pthread_mutex_t * mutex); int pthread_mutex_unlock (pthread_mutex_t * mutex); int pthread_mutex_destroy(pthread_mutex_t * mutex); NÁVRATOVÁ HODNOTA Úspěšné volání = 0 Jinak - kód chyby

Semafory vláken #include <semaphore.h> ZÁKLADNÍ FUNKCE PRO PRÁCI SE SEMAFORY: int sem_init (sem_t *sem, int pshared, unsigned int value); int sem_wait (sem_t *sem); int sem_post (sem_t *sem); int sem_destroy (sem_t *sem);

Semafory vláken - pokračování sem_wait (&sem); a) funkce v případě nenulové hodnoty semaforu ji dekrementuje o 1; b) pokud je hodnota semaforu nulová, čeká dokud se nezmění; pak se provede bod a) sem_post (&sem); Funkce automaticky inkrementuje hodnotu semaforu o 1.

Signály ve vláknech Problematika signálů je obecně vysvětlena v části vysvětlující komunikaci mezi procesy. Vyslání signálu danému procesu : int kill (int pid, int signal); V případě vláken je lepší používat funkci: pthread_kill(pthread_t thread, int signal);

Signály ve vláknech - pokračování Stejné jako v případě signálů mezi procesy Zpracování signálů: # include <signal.h> signal(int sig, void (*func)(int)); nebo lépe int sigaction (int sig, const struct sigaction *act, struct sigaction *oact);

Komunikace mezi procesy Signály oznamují procesu, že došlo k nějaké události; chovají se jako programová přerušení - objevují se asynchronně vůči běhu procesu; signály může odesílat: * jádro operačního systému * jeden proces druhému (nebo sám sobě)

Způsoby generování Signály - generování * jádro generuje některé signály na základě chybových stavů procesu (např. SIGSEGV chyba adresace mimo adresový prostor procesu, SIGFPE neplatná matematická operace při výpočtu v pohyblivé řádové čárce) * z příkazového řádku příkazem kill - např. ukončení programu s PID 12587pomocí signálu SIGKILL $ kill -KILL 12587 * pomocí vybraných terminálových znaků - např. stisk Ctrl C generuje signál SIGINT (ukončení probíhajícího procesu), Ctrl \ - SIGQUIT (programové přerušení procesu)

* z procesu - voláním funkce: Signály - generování kde int kill (int pid, int signal); pid > 0 PID konkrétního procesu, kterému bude poslán signál 0 signál poslán všem procesům skupiny (s výjimkou vybraných systémových), do níž proces patří -1 signál poslán všem procesům (až na vybrané systémové - dle implementace); standard POSIX chování funkce pro tuto hodnotu nespecifikuje pid < -1 signál poslán všem procesům jejichž identifikace skupiny je shodná s absolutní hodnotou pid V případě vláken je lepší používat funkci: pthread_kill(pthread_t thread, int signal);

Signály - zpracování Způsoby zpracování v procesu 1. Implicitní zpracování; 2. Ignorování signálu; 3. Zpracování pomocí určené funkce - specifikované pomocí volání jádra signal()- NENÍ ve standardu POSIX! void (*signal(int sig, void (*func)(int)))(int); kde sig - specifikace signálu, který má být odchycen func - funkce, která bude volána po obdržení signálu

# include <signal.h> Signály - zpracování void (*signal(int sig, void (*func)(int)))(int); kde sig - specifikace signálu, který má být odchycen func - adresa funkce, která bude volána po obdržení signálu sig nebo jedna z hodnot: SIG_IGN SIG_DFL signál bude ignorován (nefunguje v případě SIGKILL) signál bude zpracován implicitním způsobem Např. signál SIGINT má být ignorován: signal (SIGINT, SIG_IGN);

Signály - příklad zpracování signálu SIGINT = Ctrl C /* Stones, Matthew str. 360 */ #include <signal.h> #include <stdio.h> #include <unistd.h> void ouch(int sig) { printf("ouch! - I got signal %d\n", sig); (void) signal(sigint, SIG_DFL); int main() { (void) signal(sigint, ouch); while(1) { printf("hello World!\n"); sleep(1);

Signály - použití volání jádra sigaction (POSIX) # include <signal.h> int sigaction(int sig, const struct sigaction *act, struct sigaction *oact); Struktura sigaction definuje akce, které se provedou po obdržení určeného signálu. SLOŽKY struktury sigaction: void (*) (int) sa_handler; /* funkce, SIG_DFL nebo SIG_IGN */ sigset_t sa_mask; /* maska signálů - tyto signály budou blokovány */ int sa_flags; /* modifikátory */ Např.: sigaction (SIGUSR1, &sa, NULL);

Signály - použití funkce sigaction Maska sa_mask se nastavuje pomocí funkcí: int sigemptyset(sigset_t *set); /*prázdná množina sig.*/ int sigfillset(sigset_t *set); /* všechny signály */ int sigaddset(sigset_t *set,int signo); /*přidání sig.*/ int sigdellset(sigset_t *set,int signo); /*odebrání sig.*/ Další funkce pro práci se signály: /* Zablokování procesu do příchodu signálu */ int pause(void); /* Vygenerování signálu SIGALRM po uplynutí určeného časového intervalu seconds */ unsigned int alarm(unsigned int seconds);

Signály - příklad použití funkce sigaction /* Příklad - Stones, Matthew str. 365 */ #include <signal.h> #include <stdio.h> #include <unistd.h> void ouch(int sig) { printf("ouch! - I got signal %d\n", sig);

/* Příklad - pokračování */ int main() { struct sigaction act; act.sa_handler = ouch; sigemptyset(&act.sa_mask); act.sa_flags = 0; sigaction(sigint, &act, NULL); while(1) { printf("hello World!\n"); sleep(1);

Semafory Semafory jsou základním mechanismem synchronizace procesů. Ve srovnání se semafory vláken jsou semafory procesů implementačně výrazně náročnější. Funkce pro práci se semafory jsou obsaženy v knihovně s hlavičkovým souborem <sys/sem.h> Vytvoření semaforu: int semget(); Provádění operací wait a post se semaforem: int semop(); Řízení semaforu: int semctl();

Příklad - binární semafor #include <sys/ipc.h> #include <sys/sem.h> #include <sys/types.h> /* Definice unie semun */ union semun { int val; struct semid_ds *buf; unsigned short int *array; struct seminfo * buf; ;

Binární semafor - alokace a dealokace int binary_semaphore_allocation (key_t key, int sem_flags) { return semget (key, 1, sem_flags); int binary_semaphore_deallocate (int semid) { union semun ignored_argument; return semctl (semid, 1, IPC_RMID,ignored_argument);

Binární semafor - inicializace /* Inicializace binárního semaforu s hodnotou 1. */ int binary_semaphore_initialize (int semid) { union semun argument; unsigned short values[1]; values[0] = 1; argument.array = values; return semctl (semid, 0, SETALL, argument);

Binární semafor - operace wait /* Čeká, pokud je hodnota rovna nule. Pokud je hodnota > 0, dekrementuje ji o 1 */ int binary_semaphore_wait (int semid) { struct sembuf operations[1]; /* Use the first (and only) semaphore. */ operations[0].sem_num = 0; /* Decrement by 1. */ operations[0].sem_op = -1; /* Permit undo ing. */ operations[0].sem_flg = SEM_UNDO; return semop (semid, operations, 1);

binární semafor - operace post /* Okamžitá inkrementace hodnoty semaforu o 1. */ int binary_semaphore_post (int semid) { struct sembuf operations[1]; /* Use the first (and only) semaphore. */ operations[0].sem_num = 0; /* Increment by 1. */ operations[0].sem_op = 1; /* Permit undo ing. */ operations[0].sem_flg = SEM_UNDO; return semop (semid, operations, 1);

Práce se soubory a zařízeními Vysokoúrovňový přístup: - funkce obsaženy ve standardní knihovně (hlavičkový soubor stdio.h); - pracuje se se souborovými proudy (streams); - stream je implementován jako pointer na strukturu FILE; - při spuštění programu se automaticky otevírají tři proudy stdin, stdout a stderr reprezentující standardní vstup, výstup a chybový výstup;

Práce se soubory a zařízeními - přístup k souboru se získá pomocí funkce: FILE *fopen(const char *filename, const char *mode); - další funkce, např.: fread(), fwrite(), fseek(), fgets(), fprintf(), fscanf() - ukončení přístupu k souboru (=uzavření proudu) pomocí funkce: int fclose(file *stream);

Práce se soubory a zařízeními Nízkoúrovňový přístup k souborům a zařízením: - každý proces má k dispozici několik deskriptorů souborů (reprezentovány čísly typu int), které slouží k přístupu k otevřeným souborům nebo zařízením; - při spuštění programu se automaticky otevírají tři zařízení: standardní vstup (0), výstup (1) a chybový výstup (2); - funkce resp. jejich parametry jsou obsaženy v knihovnách s hlavičkovými soubory unistd.h, sys/types.h a sys/stat.h;

Práce se soubory a zařízeními - pokračování - nový deskriptor soubor se získá pomocí funkce: int open(const char *path, int oflags[,int mode]); Např.: fd = open( /dev/tty,o_rdw); nebo in = open( file.out,o_wronly O_CREAT, S_IRUSR S_IWUSR); - další funkce, např.: read(), write(), ioctl(), lseek(), fstat(); - ukončení přístupu k souboru (=uvolnění deskriptoru): int close(int filedesc);

Listing 4.15 (thread-pid) Print Process IDs for Threads #include <pthread.h> #include <stdio.h> #include <unistd.h> void* thread_function (void* arg) { fprintf (stderr, child thread pid is %d\n, (int) getpid ()); /* Spin forever. */ while (1); return NULL;

Listing 4.15 (thread-pid) Print Process IDs for Threads int main () { pthread_t thread; fprintf (stderr, main thread pid is %d\n, (int) getpid ()); pthread_create (&thread, NULL, &thread_function, NULL); /* Spin forever. */ while (1); return 0;

Job Queue Thread Function, Protected by a Mutex #include <malloc.h> #include <pthread.h> struct job { /* Link field for linked list. */ struct job* next; /* Other fields describing work to be done... */ ; /* A linked list of pending jobs. */ struct job* job_queue; /* A mutex protecting job_queue. */ pthread_mutex_t job_queue_mutex = PTHREAD_MUTEX_INITIALIZER;

/* Process queued jobs until the queue is empty. */ void* thread_function (void* arg) { while (1) { struct job* next_job; /* Lock the mutex on the job queue. */ pthread_mutex_lock (&job_queue_mutex); /* Now it s safe to check if the queue is empty. */ if (job_queue == NULL) next_job = NULL; else { /* Get the next available job. */ next_job = job_queue; /* Remove this job from the list. */ job_queue = job_queue->next;

/* Unlock the mutex on the job queue because we re done with the queue for now. */ pthread_mutex_unlock (&job_queue_mutex); /* Was the queue empty? If so, end the thread. */ if (next_job == NULL) break; /* Carry out the work. */ process_job (next_job); /* Clean up. */ free (next_job); return NULL;

Synchronizace vláken pomocí MUTEXů (příklad) #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <pthread.h> #include <semaphore.h> void *thread_function(void *arg); pthread_mutex_t work_mutex;

#define WORK_SIZE 1024 char work_area[work_size]; int time_to_exit = 0; int main() { int res; pthread_t a_thread; void *thread_result; res = pthread_mutex_init(&work_mutex, NULL); if (res!= 0) { perror("mutex initialization failed"); exit(exit_failure);

res = pthread_create(&a_thread, NULL, thread_function, NULL); if (res!= 0) { perror ("Thread creation failed"); exit (EXIT_FAILURE);

pthread_mutex_lock(&work_mutex); printf("input some text. Enter 'end' to finish\n"); while(!time_to_exit) { fgets(work_area, WORK_SIZE, stdin); pthread_mutex_unlock(&work_mutex); while(1) { pthread_mutex_lock(&work_mutex); if (work_area[0]!= '\0') { pthread_mutex_unlock(&work_mutex); sleep(1); else { break;

pthread_mutex_unlock(&work_mutex); printf("\nwaiting for thread to finish...\n"); res = pthread_join(a_thread, &thread_result); if (res!= 0) { perror("thread join failed"); exit(exit_failure); printf("thread joined\n"); pthread_mutex_destroy(&work_mutex); exit(exit_success);

void *thread_function(void *arg) { sleep(1); pthread_mutex_lock(&work_mutex); while(strncmp("end", work_area, 3)!= 0) { printf("you input %d characters\n", strlen(work_area) -1); work_area[0] = '\0'; pthread_mutex_unlock(&work_mutex); sleep(1); pthread_mutex_lock(&work_mutex); while (work_area[0] == '\0' ) { pthread_mutex_unlock(&work_mutex); sleep(1); pthread_mutex_lock(&work_mutex);

time_to_exit = 1; work_area[0] = '\0'; pthread_mutex_unlock(&work_mutex); pthread_exit(0);