Search
Výchozí soubory prga-lab12-sources.zip bab36prga-lec11-codes.zip
MPA
Cílem cvičení je implementovat program s více paralelně běžícími vlákny z přednášky lec11 a následně jej rozšířit do programu ovládající jinou aplikaci prostřednictvím komunikace pojmenovanou rourou, viz Lab 10 - Meziprocesová komunikace.
Můžeme využít výchozí soubor main.c ve kterém máme připraveny funkce pro tři různá vlákna:
main.c
input_thread()
output_thread()
alarm_thread()
Perioda časovače může být nastavována uživatelem, stiskem definovaných kláves. Použití vláken je založeno na knihovně pthread (POSIX threads) a příklad demonstruje použití základních konstrukcí pthread knihovny.
pthread
main()
"\rAlarm period: %10i Alarm counter: %10i"
Pro čtení kláves bez nutnosti potvrzovat Enter přepněte terminál do raw režimu, například tak, jak bylo prezentována v přednášce lec11.
Enter
raw
Například funkce call_termios()
void call_termios(int reset) { static struct termios tio, tioOld; tcgetattr(STDIN_FILENO, &tio); if (reset) { tcsetattr(STDIN_FILENO, TCSANOW, &tioOld); } else { tioOld = tio; //backup cfmakeraw(&tio); tcsetattr(STDIN_FILENO, TCSANOW, &tio); } }
Použijte strukturu pro zapouzdření proměnných sdílených jednotlivými vlákny.
typedef struct { int alarm_period; int alarm_counter; bool quit; pthread_mutex_t *mtx; // avoid global variables for mutex and pthread_cond_t *cond; // conditional variable } data_t; // data structure shared among the threads
Použijte kritickou sekci (mutex) pro přístup ke sdíleným datům.
Např. ve výstupním vlákně
pthread_mutex_lock(&mtx); pthread_cond_wait(&cond, &mtx); // wait for next event q = data->quit; printf("\rAlarm time: %10i Alarm counter: %10i", data->alarm_period, data->alarm_counter); fflush(stdout); pthread_mutex_unlock(&mtx);
Nebo ve vlákně alarm_thread() při počátační incializaci lokálních proměnných
pthread_mutex_lock(&mtx); bool q = data->quit; useconds_t period = data->alarm_period * 1000; // alarm_period is in ms pthread_mutex_unlock(&mtx);
Použijte zasílání signálů pro komunikaci mezi vlákny a zabránění plýtvání výpočetním výkonem. Fakticky je nutné překreslit výstup ve vlákně (funkci) output_thread() pouze pokud došlo k nějaké změně, uživatelský vstup nebo zvýšení hodnoty čítače.
Například ve vlákně alarm_thread()
while (!q) { usleep(period); // calling usleep out of critical section!!! pthread_mutex_lock(&mtx); q = data->quit; data->alarm_counter += 1; period = data->alarm_period * 1000; // update the period is it has been changed pthread_cond_broadcast(&cond); // inform all waiting threads on cond. pthread_mutex_unlock(&mtx); }
flush
stdout
fflush(stdout);
quit
bool quit = false; ... getchar(); pthread_mutex_lock(&mtx); quit = true; pthread_mutex_unlock(&mtx); ...
V další části cvičení pokračujte směrem k implementaci vícevláknová aplikace s meziprocesovou komunikací, realizovanou pojmenovanou rourou (vizte Lab 10). Program “rozdělte” na dva programy.
mpa-alrm
mpa-ctrl
Budeme uvažovat následující jednobajtovou komunikaci.
Program mpa-ctrl reaguje je na stisk kláves 'e', 'd', 'p', 'r' definované komunikace. Dále reaguje na
Pojmenované roury mohou být například
/tmp/mpa-alrm.in
/tmp/map-ctrl.in
Vytvoření pojmenovaných rour
#!/bin/sh in=/tmp/mpa-alrm.in out=/tmp/mpa-ctrl.in rm -rf $in $out mkfifo $in mkfifo $out
V obou programech použijeme neblokující čtení/zápis z/do souboru prostřednictvím knihovny prg_io_nonblock.c.
prg_io_nonblock.c
thread_barrier.c