Cvičení č. 2 Komunikace mezi procesy Program Hodiny 4 body
Datum: 6.2.2009
1
Obsah 1. Úvod.............................................................................................................................................2 2. Pokyny pro odevzdání..................................................................................................................2 3. Příprava ........................................................................................................................................3 4. Úlohy............................................................................................................................................3 4.1. Požadavky na program Hodiny.............................................................................................3 4.2. Požadavky na implementaci..................................................................................................3 4.3. Komunikace s Grafickým uživatelským rozhraním..............................................................3 4.4. Doporučení pro implementaci...............................................................................................4 4.5 Přehled zpráv a funkcí GUI Hodiny ......................................................................................6
1. Úvod V tomto cvičení si vysvětlíme možnosti komunikace mezi procesy. Vytvoříme ukázkové programy s využitím systému RTMON demonstrující komunikaci mezi procesy pomocí schránek. Cílem cvičení je získat představu o problematice komunikace mezi jednotlivými procesy v prostředí více procesního operačního systému a na ukázkových programech získat praktické zkušenosti s řešením této problematiky. V rámci cvičení bude nejprve vyzkoušen ukázkový program, ve kterém jeden proces periodicky posílá data druhému procesu přes schránku a druhý proces je zobrazuje na obrazovce. Dále bude vytvořen program pro řízení hodin. Proces reagující na příkazy uživatele (nastavení času) bude komunikovat s procesem zajišťujícím běh hodin pomocí schránky. Krátce se také zmíníme o správném postupu tvorby (nejen real-time) aplikací – od návrhu až po ladění vytvořeného programu.
2. Pokyny pro odevzdání Výstupem cvičení bude protokol – krátká zpráva o řešení úloh na cvičení. Šablonu protokolu si stáhněte z Moodle. Protokol by měl obsahovat odpovědi na otázky, zdrojový kód Vašich řešení podle zadání, případně stručný popis úprav v ukázkovém kódu podle bodu 4 v tomto dokumentu. Dále bude výstupem cvičení zdrojový kód programu hodiny.cpp vypracovaný dle zadání níže. Zdrojový kód musí být přehledně formátovaný a komentovaný. Oba soubory (protokol i zdrojový kód) pojmenujte svým jménem ve formátu Prijmeni_Jmeno, a zabalte to archivu ZIP. Soubor ZIP také pojmenujte svým jménem podle výše uvedeného vzoru a odevzdejte na Moodle.
2
3. Příprava Prostudujte si prezentaci na Moodle – Komunikace mezi procesy. Pokud si nejste jisti strukturou programu s RTMON, zopakujte si informace obsažené v dokumentu „Postup vytváření programu s RTMON“.
4. Úlohy o Přeložte a spusťte ukázkový program schranky.cpp. Program obsahuje 2 procesy. Jeden proces periodicky posílá data druhému procesu přes schránku a druhý proces je zobrazuje na obrazovce. o Upravte program tak, aby proces 2 četl zprávy ze schránky bez čekání (pomocí funkce rtm_read_q). Využijte přitom toho, že funkce vrací nulu, jestliže úspěšně přečetla ze schránky zprávu. Pokud tedy ve schránce byla zpráva, vrátí funkce hodnotu 0. Proces 2 při tomto způsobu čtení zpráv upravte tak, aby byl spouštěn periodicky (odstraňte smyčku while). Kód upraveného procesu vložte do protokolu. o Vytvořte program Hodiny podle zadání uvedeného níže. Stáhněte si z Moodle potřebné knihovny a ukázkový program, které najdete v archivu Hodiny.zip. Vytvořený soubor pak přidejte k protokolu viz pokyny pro odevzdání výše.
4.1. Požadavky na program Hodiny o Program bude komunikovat s grafickým rozhraním Hodiny-GUI. Veškerý výstup z programu a vstup do programu se bude odehrávat přes toto rozhraní. o Program bude zobrazovat aktuální čas ve formátu HH:MM.SS o Aktuální čas (hodiny a minuty) bude možno nastavit. o Program bude implementován podle požadavků uvedených níže.
4.2. Požadavky na implementaci o Program bude napsán v jazyku C s využitím OS RTMON pro zajištění souběžného provádění úloh. o Program bude obsahovat jeden proces pro běh hodin a jeden proces pro komunikaci s uživatelským rozhraním – pro nastavení hodin o Proces pro komunikaci s GUI bude v případě změny času předávat procesu hodin nově nastavený čas pomocí schránky OS RTMON.
4.3. Komunikace s Grafickým uživatelským rozhraním Program bude využívat grafické uživatelské rozhraní dostupné přes soubory clock_gui.h a clock_gui.cpp. Program bude od GUI přijímat následující zprávu: MSG_CLOCK_SETTIME Parametrem zprávy je nově nastavená hodnota hodin ve formátu Hodiny * 1000 + Minuty. 3
Váš program tedy získá hodnotu nastaveného času z GUI takto: Clock_GetMessage(&msg, &data); Switch ( msg ) { case MSG_CLOCK_SETTIME: hod = data / 1000; min = data - (hod * 1000); // TODO: predat cas do procesu aktualizace hodin break; } Pro ovládání GUI může program využít následující funkce deklarované v souboru clock_gui.h: bool Clock_DisplayTime(int hour, int min, int sec);
Funkce zobrazí v grafickém rozhraní (simulátoru hodin) zadaný čas. Měla by být tedy volána periodicky každou sekundu z procesu zajišťujícího běh hodin. bool Clock_Init();
Funkce inicializuje grafické rozhraní (simulátor). Musí být zavolána před prvním použitím funkcí rozhraní. void Clock_Exit();
Funkce ukončí práci grafického rozhraní. Měla by být zavolána na konci Vašeho programu.
4.4. Doporučení pro implementaci Využijte připravenou kostru programu v souboru hodiny.cpp, který najdete v archivu Hodiny.zip na Moodle. V této šabloně můžete pouze doplnit chybějící kód na místech označených „TODO“. Vytvářejte program postupně, krok za krokem. U programu jehož funkčnost je realizována pomocí několika procesů se automaticky nabízí postupně přidávat jednotlivé procesy. Také v rámci každého procesu můžete jeho funkčnost vytvářet postupně, vždy po odzkoušení správného fungování předchozí části kódu. Prvním krokem může být například vytvoření periodicky spouštěného procesu, který bude zobrazovat hodiny. Teprve po ověření funkce tohoto procesu přidávejte další funkce. Následujícím krokem by mohlo být např. implementovat proces pro komunikaci s GUI, který bude vypisovat přijaté příkazy do okna konzoly (printf). Teprve po ověření funkčnosti předávání správ pak přidáme schránku a kód pro odesílání změněného času. Zde může být opět vhodné nejprve ověřit komunikaci zápisem pevně dané hodnoty času z vysílajícího procesu (např. času 12:30) a teprve po odladění zapisovat skutečně nastavený čas.
4
Pro předání času přes schránku můžete zvolit libovolný formát. Elegantním řešením bude použít strukturu, obsahující nastavenou hodinu a minutu. Struktura by mohla být definována např. takto: struct Cas { int hodina; int minuta; };
Schránka pro předávání této struktury pak musí mít velikost sizeof(Cas). Definovala by se tedy takto: rtm_create_q(„schr1“, sizeof(Cas), 1, &s1); Strukturu s informacemi o čase pak nadefinujeme a zapíšeme do schránky např. takto: Cas data; data.hodina = 22; data.minuta = 0; rtm_write_q(s1, &data);
Je ale také možno předávat nastavený čas jako celé číslo, zakódovaný např. jako Hodiny * 1000 + minuty, takže čas 22:30 by se předal jako číslo 22030 (22 x 1000 + 30). Pro aktualizaci hodin bude vhodné použít periodicky spouštěný proces, který při každém spuštění zvětší aktuální čas o 1 sekundu. Je třeba samozřejmě ošetřit aby po 59 sekundách se zvýšilo počitadlo minut atd. Kód by mohl vypadat následovně: sekundy++; if ( sekundy > 59 ) { minuty++; sekundy = 0; … atd. Pro přečtení (případně) změněného času v procesu aktualizace hodin nemůžeme samozřejmě použít funkci pro čtení ze schránky s čekáním (rtm_read_q_w) protože ta by způsobila pozastavení procesu až do příchodu zprávy – a čas na hodinách by se tedy nezvětšoval. Navíc pozastavení periodicky spouštěného procesu na dobu delší než je jeho perioda spuštění je v systému RTMON považováno za chybový stav. Využijte proto toho, že funkce pro čtení zprávy ze schránky bez čekání (rtm_read_q) vrací nulu, jestliže úspěšně přečetla ze schránky zprávu. Proces se tedy může pokoušet v každé periodě přečíst zprávu, ale pouze pokud je čtení úspěšné provede aktualizaci svých proměnných, ve kterých je uložen aktuální čas. Můžete také prozkoumat další zprávy a funkce grafického rozhraní Hodiny, viz následující přehled.
5
4.5 Přehled zpráv a funkcí GUI Hodiny Zprávy posílané z GUI do vašeho programu MSG_CLOCK_SETTIME Uživatel nastavil nnový čas. Datový parametr zprávy obsahuje nastavenou hodinu a minutu ve formátu Hodiny * 1000 + Minuty. MSG_CLOCK_SETALARM Uživatel nastavil nový čas budíku. Datový parametr zprávy obsahuje nastavenou hodinu a minutu budíku ve formátu Hodiny * 1000 + Minuty. MSG_CLOCK_ENABLE_ALARM Uživatel povolil budík (může zvonit). MSG_CLOCK_DISABLE_ALARM Uživatel zakázal budít (nemá zvonit) MSG_CLOCK_SNOOZE Uživatel stiskl tlačítko pozastavení budíku (Snooze – zdřímnout si).
Přehled funkcí GUI hodiny (clock_gui.h a cpp) bool Clock_DisplayTime(int hour, int min, int sec);
Funkce zobrazí v grafickém rozhraní (simulátoru hodin) zadaný čas. Měla by být tedy volána periodicky každou sekundu z procesu zajišťujícího běh hodin. bool Clock_Init();
Funkce inicializuje grafické rozhraní (simulátor). Musí být zavolána před prvním použitím funkcí rozhraní. void Clock_Exit();
Funkce ukončí práci grafického rozhraní. Měla by být zavolána na konci Vašeho programu. int Clock_GetMessage(int* msg, int* data, bool wait = false);
Funkce vrací poslední zprávu, kterou poslalo uživatelské rozhraní Vašemu programu. Parametry int* msg [out] – ukazatel na proměnnou, do které bude uložen kód zprávy, viz konstanty výše, např. MSG_CLOCK_SETTIME. int* data [out] - ukazatel na proměnnou, do které budou uložena data zprávy. Pokud zpráva data nemá (napotřebuje), bude zde hodnota 0. bool wait [in] - Příznak určující, zda se má čekat na zprávu od GUI, pokud v okamžiku zavolání funkce žádná zpráva není ve vyrovnávací paměti. Pokud je true, funkce bude čekat (proces, který ji zavolal bude pozastaven!). Pokud je false, funkce ihned pokračuje dále. Návratová hodnota Pokud je získána zpráva, vrací funkce nenulovou hodnotu. Pokud zpráva není získána (např. protože žádná nepřišla a parametr wait je false), vrací funkce nulu.
6
bool Clock_StartAlarm();
Funkce spustí budík. Pozor! Zvuk budíku není právě příjemný a o jeho ukončení se musí postarat Váš program. bool Clock_StopAlarm();
Funkce zastaví (umlčí) budík.
5. Odkazy Moodle – podpora předmětu na http://vyuka.fai.utb.cz. Magisterské Studium, Programování realtime aplikací. Klíč k zápisu je REAL09. Schranky.zip – Kód ukázkového programu schránky.cpp Hodiny.zip – Knihovny a ukázkový program pro úkol Hodiny.
7