{{indexmenu_n>10}} ======== HW 9B - Vícevláknová aplikace s meziprocesovou komunikací ======== ^ Termín odevzdání |** 22.05.2024@09:00 CEST (st) ** | ^ Povinné zadání | [[courses:bab36prga:hw:hw9|HW 9]] | ^ Volitelné zadání | není | ^ Bonusové zadání | 5b | ^ Počet uploadů | bez omezení | ^ Výchozí soubory | {{ :courses:bab36prga:hw:bab36prga-hw9b.zip |}} | ^ Výchozí soubory | [[courses:bab36prga:hw:hw9bhints|Doporučený postup při vypracování HW9B]]| Cílem úlohy je rozvést zkušenosti s využitím pojmenované roury pro komunikaci aplikace v počítači s poskytnutým Modulem a s prací s více vlákny pro zpracování více zdrojů událostí. Specifikum práce s pojmenovanou rourou je, že při otevření souboru (roury) pro zápis musí být roura otevřena pro čtení, aby bylo kam případně ukládat data. Proto je volání ''io_open_write()'' blokované. Řešením je tak spustit program generátoru signálu''./binaries/bab36prga-hw9b-sigen'' nebo vyčítání roury programem ''tail -f /tmp/sigen.in''. /* HW9B vychází z HW9, kterou je možné přímo rozšířit o výpočet fraktálu a využití fronty pro komunikaci mezi vlákny. */ ====== Povinné zadání ====== Implementujete více-vláknový program, který bude komunikovat s programem generujícím signál (''sigen'') prostřednictvím pojmenované roury, ovládat generování signálu (nastavovat parametry) a vyčítat generovaný signál, který zobrazí v grafickém okně s využitím přiložené knihovny ''xwin_otk_plot'' založené na grafické knihovně ''otk_lib''. Komunikační protokol probíhá prostřednictvím zpráv definovaných v přiložených souborech ''messages.h'' a ''messages.c'', které obsahují funkce pro //marshaling// a //unmarshaling// struktur zpráv do/z pole bajtů. Od programu se očekává následující funkcionalita: * Program využívá samostatná vlákna pro zpracování vstupu z klavesnice, čtení zpráv z generátoru ''sigen'' (pojmenovaná roura) a hlavní vlákna. * K synchronizace můžete využít přiloženou implementaci fronty zpráv ''event_queue.h'' a ''event_queue.c''. * Program nastavuje generátor a spouští generování signálu, který zobrazuje prostřednictvím přiložené knihovny funkcí ''xwin_set_plot()'' a ''xwin_redraw_plot()''. * Nastavuje parametry generátoru EKG (ECG) signálu //heart_rate_mean//, //low_frequency//, //high_frequency// a //low_high_frequency_ratio//, například klávesami '1' až '8' a to v rozsahu definovaném v ''message.h''. * Na stisk klávesy ''g'' reaguje zasláním zprávy ''MSG_GET_VERSION'' a následně zobrazí odpověď. * Na stisk klávesy ''s'' reaguje zasláním zprávy ''MSG_SET_SIGNAL'' s aktuálním nastavením generátoru signálu. * Na stisk klávesy ''r'' reaguje zasláním požadavku na generování signálu ''MSG_SIGNAL'', který následně přijme a zobrazí v grafu. **Signál je zaslán v jedné nebo několika zprávách o maximální delce 128 hodnot.** * Přijem signálu je možné přerušit stiskem klávesy ''a''. * Na stisk klávesy ''c'' reaguje smazáním grafu. * Program je korektně ukončen po stisku klávesy ''q''. * **Úkol**: Implementujte generování, příjem a zobrazení několika signálu (vícenásobné zaslání ''MSG_SIGNAL'') ideálně každý s jiným nastavením. Program bude po stisku klávesy ''b'' automaticky komunikovat s generátorem, spouštět genrování signálu a nastavovat jeho parametry. Generování je možné kdykoliv přerušit stiskem klávesy ''a'' (abort). {{:courses:bab36prga:hw:prga-hw9.png?400|}} OTK je jednoduchá knihova grafických prvků implementovaná v OpenGL. Kompilace může vyžadovat instalaci potřebných knihoven. Např. v operačním systému založeném na Ubuntu to může být ''libxmu-dev'' tedy ''apt install libxmu-dev''. ===== Ovládací aplikace ===== Ovladací aplikace ''sigen'' je více-vláknovým program, který reaguje na stisk kláves, vstup z pojmenované roury a zapisuje do pojmenované roury. Program má dva volitelné argumenty, kterými jsou pojmenovaná roura vstupu a pojmenovaná roura výstupu. Výchozí hodnoty odpovídají volání: ./sigen /tmp/sigen.in /tmp/sigen.out Po spouštení program zasílá (zapisuje do výstupní pojmenované roury) zprávu ''MSG_STARTUP'', která obsahuje textovou zprávu "PRG-SIGEN". Program reaguje na příjem zpráv (viz komunikační protokol) a generuje signál, jehož parametry lze měnit zasláním zprávy ''MSG_SET_SIGNAL'' Program reaguje na stisk následujících kláves * ''a'' - **ABORT** - Přerušení generování (posílání signálu) a zaslání zprávy ''MSG_ABORT''. * ''r'' - **REBOOT** - Soft "restart" generátoru, zašle zprávu ''MSG_STARTUP'' podobně jako při spuštení programu. * ''q'' - **QUIT** Ukončení programu. ===== Komunikační protokol ===== Program ''sigen'' generuje signál dle zadaných parametrů, které jsou zasílány z ovládací aplikace zprávou ''MSG_SET_SIGNAL''. Vlastní generování probíhá tak, že řídicí aplikace zašle zprávu ''MSG_SIGNAL'', na kterou ''sigen'' reaguje zasláním několika zpráva ''MSG_SIGNAL_DATA'' s obsahem hodnot definující konkrétní rozsah signálu. Definice jednotlivých zpráv odpovídá definici složeného typu ''struct message'' v souboru ''message.h''. // Definition of the communication messages typedef enum { MSG_OK, // ack of the received message MSG_ERROR, // report error on the previously received command MSG_ABORT, // abort - from user button or from serial port MSG_DONE, // report the requested work has been done MSG_GET_VERSION, // request version of the firmware MSG_VERSION, // send version of the firmware as major,minor, patch level, e.g., 1.0p1 MSG_STARTUP, // init message (id, up to 9 bytes long string, cksum) MSG_SET_SIGNAL, // set signal parameters MSG_SIGNAL, // request signal of a batch of tasks (chunk_id) MSG_SIGNAL_DATA, // computed result (chunk_id, result) MSG_NBR } message_type; typedef struct { uint8_t major; uint8_t minor; uint8_t patch; } msg_version; typedef struct { uint8_t message[STARTUP_MSG_LEN]; } msg_startup; #define HEART_RATE_MEAN_MIN 10.0 #define HEART_RATE_MEAN_MAX 200.0 #define LOW_FREQ_MIN 0.1 #define LOW_FREQ_MAX 0.5 #define HIGH_FREQ_MIN 0.25 #define HIGH_FREQ_MAX 1.0 #define LOW_HIGH_FREQ_RATIO_MIN 0.0 #define LOW_HIGH_FREQ_RATIO_MAX 1.0 typedef struct { double heart_rate_mean; // default: 60; 10--200; double low_frequency; // default: 0.1; 0.1--0.5; double high_frequency; //default: 0.25; 0.25--1.0; double low_high_frequency_ratio; //default: 0.5 0-1; } msg_set_signal; typedef struct { uint8_t cid; // chunk id uint8_t n; // actual no. of valid data values float values[SIGNAL_DATA_SIZE]; } msg_signal_data; typedef struct { uint8_t type; // message type uint8_t cksum; // message command union { msg_version version; msg_startup startup; msg_set_signal set_signal; msg_signal_data signal_data; } data; } message; Inicializační zpráva ''MSG_STARTUP'' je definována jako message msg = { .data.startup.message = { 'P', 'R', 'G', '-', 'S', 'I', 'G', 'E', 'N' } }; === Výměna zpráv a průběh komunikace === * Po startu program posílá zprávu ''MSG_STARTUP'' * Na příjem zprávy ''MSG_GET_VERSION'' odpovídá ''MSG_VERSION'' nebo ''MSG_ERROR'' * Na příjem zprávy ''MSG_SET_SIGNAL'' odpovídá Nucleo ''MSG_OK'' nebo ''MSG_ERROR'' (v případě, že požadované parametry jsou mimo definovaný rozsah). * Na příjem zprávy ''MSG_SIGNAL'' odpovídá ''MSG_OK'' a zahajuje generování signálu nebo v případě chyby posílá ''MSG_ERROR''. Generovaný signál je posílán postupně v několika zprávách ''MSG_SIGNAL_DATA''. Po dokončení výpočtu zasílá zprávu ''MSG_DONE''. * Generování je možné přerušit zasláním zprávy ''MSG_ABORT'', na kterou odpovídá ''MSG_OK'' a přeruší a ukončí aktuáně probíhající generování/zasílání signálu. * Po přerušení posílá zprávu ''MSG_ABORT''. * Přerušení je možné také stiskem klávesy 'a'. V případě zaslání zprávy ''MSG_SET_SIGNAL'' nebo i ''MSG_SIGNAL'' jsou nastaveny nové hodnoty a generování signálu pokračuje podle posledně zadaných hodnot. Kdykoliv (i v případě běžícího generování signálu) je možné si vyžádat verzi programu zasláním zprávy ''MSG_GET_VERSION'', na kterou generátor promptně odpovídá ''MSG_VERSION''. Typický průběh komunikace mezi PC a Nucleo deskou může vypadat například následovně: * //sigen//: ''MSG_STARTUP'' * //Prog.//: ''MSG_GET_VERSION'' * //sigen//: ''MSG_VERSION'' * //Prog.//: ''MSG_SET_SIGNAL'' * //sigen//: ''MSG_OK'' * //Prog.//: ''MSG_SIGNAL'' * //sigen//: ''MSG_OK'' * //sigen//: ''MSG_COMPUTE_DATA'' * //sigen//: ''MSG_COMPUTE_DATA'' * //sigen//: ''MSG_COMPUTE_DATA'' * //sigen//: ''MSG_COMPUTE_DATA'' * ... * //sigen//: ''MSG_COMPUTE_DATA'' * //sigen//: ''MSG_DONE'' ==== Doporučený postup implementace ==== Doporučený postup implementace a tipy k implementaci naleznete zde [[courses:bab36prga:hw:hw9bhints|Doporučení a tipy pro HW 9B]] ====== Odevzdávané soubory ====== Odevzdávejte zip archiv, který bude obsahovat všechny podpůrné soubory, které jste dostali k dispozici, implementovanou logiku aplikace ''prga-hw9b-main.c'', implementovanou frontu ''event_queue.c'', a všechny další soubory, které využíváte. ====== Odevzdání a hodnocení ====== /* Veřejné příklady + Makefile: {{ :courses:bab36prga:hw:bab36prga-hw09.zip |}} */ Program pokud možno realizujte na cvičení, nahrajte do odevzdávacího systému. Funkčnost programu ověří učitel. ^ ^ Povinné zadání ^ ^ Název v BRUTE | HW9B | ^ Odevzdávané soubory | ''prga-hw9b-main.c'', ''event_queue.c'', podpůrné soubory | ^ Argumenty při spuštění | žádné | ^ Procvičované oblasti | vlákna, pojmenovaná roura |