10.07.2015 Views

06 Realno vreme.pdf - Programiranje u Realnom Vremenu

06 Realno vreme.pdf - Programiranje u Realnom Vremenu

06 Realno vreme.pdf - Programiranje u Realnom Vremenu

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

: Timer2: tick ( ): TimerInterruptactive1: tick ( ): TimerController3: tick ( ): Timer4: timeout ( ): Timeable5: tick ( ): Timer


5: tick ( ): TimerInterrupt : TimerController 2: sign ( )activesynchronous6: tick ( ): Timersynchronous1: new7: stop ( )aClient4: unsign ( ): Timer3: delete


Kako do objekta TimerController stižukonkurentne poruke sa dve strane, odobjekta InterruptHandler poruka tick()i od objekata Timer poruke sign() iunsign(), ovaj objekat mora da budesinhronizovan (monitor). Slično važi i za objekte klase Timer. Ovoje prikazano na sledećem dijagramuscenarija, pri čemu su blokirajući poziviisključivih operacija označeni precrtanimstrelicama


1: tick ( ) 2: tick ( ): TimerInterrupt : TimerControllersynchronous: Timer3: timeout ( )5: unsign: TimeraClient : Timeable4: delete


Ovakav mehanizam dovodi do sledećeg problemaprikazanog na predhodnom dijagramu: Može se dogoditi da se unutar istog toka kontrole (niti) kojipotiče od objekta TimerInterrupt, pozoveTimerController::tick(), čime se ovaj objekat zaključavaza nove pozive svojih operacija, zatim odatle pozoveTimer::tick(), brojač dobrojava do nule, poziva seTimeable::timeot(), a odatle neka korisnička funkcija.Unutar ove korisničke funkcije može se, u opštem slučaju,kreirati ili brisati neki Timer, sve u kontekstu iste niti, čimese dolazi do poziva operacija objekta TimerController, kojije ostao zaključan. Na taj način dolazi do kružnog blokiranja(engl. deadlock) i to jedne niti same sa sobom.


Čak i ako se ovaj problem zanemari, ostajeproblem eventualno predugog zadržavanja unutarkonteksta niti koja ažurira brojače, jer se nemože kontrolisati koliko traje izvršavanjekorisničke operacije timeout(). Time seneodreĎeno zadržava mehanizam ažuriranjabrojača, pa se gubi smisao samog merenja<strong>vreme</strong>na.


2: tick ( ): Timersynchronous: TimerInterrupt1: tick ( ): TimerController3: signal (activesynchronous6: unsign (: TimerThreadactive: Timer4: timeout ( )5: deleteaClient : Timeable


: TimerInterrupt : TimerController1: tick ( )2: tick ( ): Timer : TimerThread aClient :Timeable3: signal ( ): Timer4: timeout ( )5: delete6: unsign ( )


Problem se može rešiti na sledeći način: potrebno jena nekom mestu prekinuti kontrolu toka i razdvojitikontekste uvoĎenjem niti kojoj će biti signalizirandogaĎaj.Ovde je to učinjeno tako što objekat Timer, ukolikoposeduje pridružen objekat Timeable, poseduje ijedan aktivni objekat TimerThread koji posedujenezavisan tok kontrole u kome se obavlja pozivoperacije timeout().Objekat Timer će, kada <strong>vreme</strong> istekne, samosignalizirati dogaĎaj pridružen objektu TimerThread ivratiti kontrolu objektu TimerController.TimerThread će, kada primi signal, obaviti pozivoperacije timeout(). Na ovaj način se navedeniproblemi eliminišu, jer se sada korisnička funkcijaizvršava u kontekstu sopstvene niti.


Klasa InterruptHandler predstavlja generalizacijuprekida. Njen interfejs izgleda ovako:typedef unsigned int IntNo; // Interrupt Numberclass InterruptHandler : public Thread {protected:InterruptHandler (IntNo num, void(*intHandler)());virtual int handle () { return 0; }void interruptHandler ();};


Korisnik iz ove apstraktne klase treba da izvede sopstvenu klasu za svakuvrstu prekida koji se koristi.Korisnička klasa treba da bude Singleton, a prekidna rutina definiše se kaostatička funkcija te klase (jer ne može imati argumente).Korisnička prekidna rutina treba samo da pozove funkciju jedinog objektaInterruptHandler::interruptHandler(). Dalje, korisnik treba da redefiniše virtuelnu funkciju handle(). Ovu funkciju ćepozvati sporadični proces kada se dogodi prekid, pa u njoj korisnik može danavede proizvoljan kod. Treba primetiti da se taj kod izvršava svaki put kadase dogodi prekid, pa on ne treba da sadrži petlju, niti čekanje na prekid. Osim navedene uloge, klasa InterruptHandler obezbeđuje i implicitnuinicijalizaciju interapt vektor tabele: konstruktor ove klase zahteva brojprekida i pokazivač na prekidnu rutinu. Na ovaj način ne može da se dogodi daprogramer zaboravi inicijalizaciju, a ta inicijalizacija je lokalizovana, pa suzavisnosti od platforme svedene na minimum.


Primer upotrebe:// Timer interrupt entry:const int TimerIntNo = 0;class TimerInterrupt : public InterruptHandler {protected:TimerInterrupt () : InterruptHandler(TimerIntNo,timerInterrupt) {}static void timerInterrupt () { instance->interruptHandler(); }virtual int handle () {... // User-defined code for one release of the sporadic process}private:};static TimerInterrupt* instance;TimerInterrupt* TimerInterrupt::instance = new TimerInterrupt;


Posao koji se obavlja kao posledica prekida logičkinikako ne pripada niti koja je prekinuta, jer se u opštemslučaju i ne zna koja je nit prekinuta: prekid je za softver signal nekog asinhronog spoljašnjegdogađaja. Zato posao koji se obavlja kao posledica prekidatreba da ima sopstveni kontekst, tj. da se pridružisporadičnom procesu, kao što je ranije rečeno.Osim toga, ne bi valjalo dopustiti da se u prekidnojrutini, koja se izvršava u kontekstu niti koja je prekinuta,poziva neka operacija koja može da blokira pozivajućunit.U svakom slučaju, prekidna rutina treba da završi svojeizvršavanje što je moguće kraće, kako ne bi zadržavalaostale prekide.


Prema tome, opasno je u prekidnoj rutini pozivati bilo kakve operacije drugihobjekata, jer one potencijalno nose opasnost od navedenih problema. Ovaj problemrešava se ako se na suštinu prekida posmatra na sledeći način:Prekid zapravo predstavlja obaveštenje (asinhroni signal) softveru da se neki događajdogodio.Pri tome, signal o tom događaju ne nosi nikakve druge informacije, jer prekidne rutinenemaju argumente.Sve što softver može da sazna o događaju svodi se na softversko čitanje podataka(eventualno nekih registara hardvera). Prema tome, prekid je asinhroni signal događaja.Navedeni problemi rešavaju se tako što se obezbedi jedan događaj koji će prekidnarutina da signalizira, i jedan proces koji će na taj događaj da čeka.Na ovaj način su konteksti prekinutog procesa (i sa njim i prekidne rutine) isporadičnog procesa koji se prekidom aktivira potpuno razdvojeni, prekidna rutinaje kratka jer samo obavlja signal događaja, a prekidni proces može da obavljaproizvoljne operacije posla koji se vrši kao posledica prekida.


typedef unsigned int IntNo; // Interrupt Numberclass InterruptHandler : public Thread {protected:InterruptHandler (IntNo num, void (*intHandler)());virtual void run ();virtual int handle () { return 0; }void interruptHandler ();private:};Event ev;


void initIVT (IntNo, void (*)() ) {// Init IVT entry with the given vector}InterruptHandler::InterruptHandler (IntNo num, void(*intHandler)()) {// Init IVT entry num by intHandler vector:initIVT(num,intHandler);}// Start the thread:start();void InterruptHandler::run () {for(;;) {ev.wait();if (handle()==0) return;}}void InterruptHandler::interruptHandler () {ev.signal();}


Pomoću raspoloživih koncepata školskog Jezgra ikorišćenjem apstrakcije Timer, potrebno je realizovatiopisani konstrukt delay koji postoji u mnogim operativnimsistemima i programskim jezicima. Korisnički programmože pozvati na bilo kom mestu operaciju delay(Time)koja suspenduje tekuću nit (u čijem se kontekstu ovaoperacija izvršava) na <strong>vreme</strong> dato argumentom. Posleisteka datog <strong>vreme</strong>na, sistem sam (implicitno) deblokiradatu nit. Data nit se može deblokirati i iz druge niti,eksplicitnim pozivom operacije Thread::wakeUp() datesuspendovane niti. Navesti precizno koje izmene trebaučiniti i gde u postojećem Jezgru i dati realizacijuoperacija delay() i wakeUp().Prikazati upotrebu ovog koncepta na primeru niti kojekontrolišu deset svetiljki koje se pale i gase naizmenično,svaka sa svojom periodom ugašenog i upaljenog svetla.


Projektuje se optimizovani podsistem za merenje <strong>vreme</strong>na u nekomReal-Time operativnom sistemu. Podsistem se zasniva na konceptu<strong>vreme</strong>nskog brojača realizovanog klasom Timer poput onog upostojećem školskom Jezgru, ali u kome <strong>vreme</strong>nski brojači služe samoza kontrolu isteka zadatog <strong>vreme</strong>nskog intervala (timeout) i u kome jeimplementacija mehanizma praćenja isteka tog intervala drugačija.Vremenski brojači, kao objekti klase Timer, uvezani su u jednostrukoulančanu listu, uređenu neopadajuće prema trenutku isteka intervalakoje brojači mere. Pri tom, prvi objekat u listi (onaj kome <strong>vreme</strong> najpreističe), u svom atributu čuva relativno <strong>vreme</strong> u odnosu na sadašnjitrenutak za koje dolazi do isteka intervala koji meri, a ostali objektiklase Timer u tom svom atributu čuvaju samo relativno <strong>vreme</strong> u odnosuna prethodni brojač u listi (može biti i 0 ukoliko dva susedna brojačaističu u istom trenutku). Na primer, ukoliko brojači u listi imaju vrednostiovog atributa redom: 1, 0, 0, 2, 5, onda to znači da prva tri brojačaističu za 1, sledeći za 3, a poslednji za 8 jedinica od sadašnjeg trenutka.Prema tome, prilikom smeštanja novog brojača u listu, on se umeće naodgovarajuću poziciju, a njegov atribut se podešava u odnosu naprethodnike, kao što je opisano. U svakom trenutku otkucaja satarealnog <strong>vreme</strong>na, ažurira se samo prvi brojač u listi. Ukoliko pri tomeprvi brojač u listi padne na nulu, <strong>vreme</strong>nski istek se signalizira onimbrojačima sa početka liste koji u svom atributu imaju nulu.


Realizovati na jeziku C++ klasu Timer premaopisanom mehanizmu. Ne koristiti gotovu strukturupodataka za ulančanu listu, već tu strukturuinkorporirati u klasu Timer. Realizovati i dve ključneoperacije ove klase:(a) Timer::start(Time t): pokreće brojač sazadatim <strong>vreme</strong>nom isteka u odnosu na sadašnjitrenutak.(b) Timer::tick(): statička funkcija klase kojuspolja poziva prekidna rutina sata realnog <strong>vreme</strong>nana svaki otkucaj (ne treba realizovati ovu prekidnurutinu). Ova operacija treba da pokrene operacijuisteka <strong>vreme</strong>na timeout() za one brojače koji suistekli.


Prilikom kreiranja, brojač se ne umeće unavedenu listu; tek prilikom startovanjase to radi. Nije potrebno realizovatinijednu drugu pomoćnu operaciju (npr.restart, očitavanje proteklog <strong>vreme</strong>naitd.), već samo opisane operacije kojesluže za kontrolu isteka zadatog intervala.TakoĎe nije potrebno voditi računa ocepanju konteksta prilikom pozivaoperacije timeout() pridruženog objektakoji se krije iza interfejsa Timeable.


Korišćenjem školskog Jezgra, potrebno jekoncept periodičnog posla realizovati klasomPeriodicTask. Korisnik može da definiše nekiperiodični posao tako što definiše svoju klasuizvedenu iz klase PeriodicTask i redefinišenjenu virtuelnu funkciju step() u kojoj navodikod za posao koji treba da se uradi u svakojperiodi. Konstruktoru klase PeriodicTaskzadaje se perioda posla tipa Time, a funkcijomstart() ove klase pokreće se posao. Prokomentarisati na koji način bi se moglorealizovati merenje WCET <strong>vreme</strong>na izvršavanjafunkcije step();


Potrebno je napisati program za kontrolu semafora za vozila sa tri svetla(crveno, žuto, zeleno). Semafor menja stanja na uobičajeni način: crveno,crveno-žuto, zeleno, žuto i tako ciklično. Vremena trajanja ovih stanjasu TR, TRY, TG i TY, respektivno. Kada se semafor pokvari, treba datrepće žuto svetlo, sa jednakim poluperiodama upaljenog i ugašenogsvetla jednakim TF; tada semafor trepće sve dok ne dođe serviser,otkloni kvar i ne resetuje semafor (semafor startuje od svog početnogstanja - start periode crvenog svetla).Svetla se kontrolišu pozivom funkcijelight(Light which, int onOff); argument which (tipaenum Light {R,G,Y}) ukazuje na svetlo, a argument onOff da li svetlotreba upaliti ili ugasiti.Neispravnost semafora uzrokuje generisanje prekida. Osim toga,poseban prekid dolazi kada se iz kontrolnog centra vrši sinhronizacijasvih semafora; tada semafor treba da pređe u unapred definisano stanje(koje se zadaje konfigurisanjem semafora).Prikazati dijagram stanja semafora, a zatim realizovati sve potrebneklase za upravljanje semaforom po datom dijagramu stanja, korišćenjemškolskog Jezgra.


Struktura:Context+request()State-state +handle()ConcreteStateA+handle()ConcreteStateB+handle()Participanti:◦ klasa Context• definiše interfejs od interesa zaklijente• održava instancu ConcreteStateX◦ klasa State• definiše interfejs za kapsulacijuponašanja pridruženog pojedinomstanju objekta klase Context◦ klasa ConcreteStateX• svaka potklasa implementiraponašanje pridruženo nekom stanjuobjekta klase Context• Kolaboracije:– kontekst prosleđuje zahteve koji su zavisni od stanja tekućem objektu konkretnogstanja– kontekst može da prosledi konkretnom objektu stanja referencu na sebe,što omogućava objektu stanja da pristupi kontekstu (npr. zahteva promenu stanja)– kontekst je primarni interfejs za klijente, klijenti ga mogu konfigurisati objektimastanja;nakon toga klijenti ne moraju da interaguju direktno sa objektima stanja


Primenljivost:◦ kada ponašanje objekta zavisi od stanja i mora semenjati u <strong>vreme</strong> izvršavanja◦ kada operacije imaju velike uslovne naredbe sa višegrana, čije izvršenje zavisi od stanja objekta• često više operacija sadrži istu uslovnu naredbu• uzorak Stanje pravi od svake grane posebnu klasukoja određuje ponašanje operacije u datom stanju


Konsekvence:◦ lokalizacija ponašanja specifičnog za stanje i razdvajanje ponašanja urazličitim stanjima• nova stanja se lako dodaju definisanjem novih potklasa stanja• nefleksibilna alternativa su uslovni iskazi svuda po kodu konteksta• veliki uslovni iskazi komplikuju održavaje koda i treba ih izbegavati◦ prelazi između stanja su eksplicitni• kada objekat definiše samostalno svoje stanje internim vrednostima,onda tranzicije nemaju eksplicitnu reprezentaciju:• predstavljaju se dodelama vrednosti promenljivim• objekti stanja štite objekat konteksta od nekonzistentnih stanja• prelazi su atomski iz perspektive konteksta• prelaz se svodi na prevezivanje jednog pokazivača◦ objekti stanja mogu biti deljeni• ako objekti stanja nemaju atribute, već je stanje koje reprezentuju kodiranou njegovom tipu – konteksti mogu da dele isti objekat stanja• tada su objekti stanja “muve” bez unutrašnjeg stanja, poseduju samoponašanje


Primer:◦ klasa TCPConnectionodržava objekat stanja(objekat potklase TCPState)koji reprezentujetekuće stanje konekcije◦ klasa TCPConnectionprosleđuje sve zahtevekoji su zavisni od stanjaobjektu stanja◦ kada konekcija menja stanjeTCPConnection objekatzamenjuje objekat stanjakoji koristiTCPConnection+open()+close()+acknowledge()-stateTCPEstablished+open()+close()+acknowledge()TCPState+open()+close()+acknowledge()TCPListen+open()+close()+acknowledge()TCPClosed+open()+close()+acknowledge()


Na ulaz računara vezan je A/D konvertor koji datianalogni signal konvertuje u digitalnu vrednostperiodično, sa dovoljno velikom frekvencijom da sesa strane softvera konvertovana digitalna vrednostmože smatrati kontinualno dostupnom. A/Dkonvertor nakon očitavanja odmah započinje sledećukonverziju.Konvertovana digitalna vrednost očitava se funkcijomreadValue():double. Ovaj signal treba modulisatiprimenom adaptivne delta modulacije na sledećinačin. Vrednost na ulazu treba očitavati (uzimatiodbirke) u <strong>vreme</strong>nskim intervalima čija je veličinaobrnuto srazmerna veličini promene signala (većapromena – češće odabiranje).


Preciznije, ako je A vrednost promene signala(razlika poslednje i pretposledenje učitanevrednosti), onda narednu vrednost treba očitatikroz T = T k *(A k /A), gde su T k i A kodgovarajuće konstante. Modulisana vredost Apredstavlja razliku poslednje i pretposledenjeučitane vrednosti. Tako modulisane vrednosti Atreba slati periodično, sa periodom T s , na izlazračunara. Jedna vrednost šalje se na izlazfunkcijom sendValue(double). Uz korišćenješkolskog Jezgra, napisati program na jeziku C++koji obavlja opisanu modulaciju.


Korišćenjem školskog Jezgra, realizovatiklasu TimedSemaphore koja obezbeđujelogiku standardnog semafora, ali uz<strong>vreme</strong>nski ograničeno čekanje.


U nekom brzom vozu postoji sistem za nadzor ispravnosti kočionogsistema koji aktivira rezervni, sigurnosni kočioni sistem u slučaju otkazaglavnog kočionog sistema. Ovaj kontrolni sistem treba da proveri da lipo aktiviranju glavne kočnice voz počinje da usporava u roku odt d = 0.5 s od trenutka aktiviranja kočnice. Ovo kašnjenje od t d podešenoje prema inerciji voza i osetljivosti senzora ubrzanja/usporenja voza, štoznači da rezervnu kočnicu ne treba aktivirati u tom roku čak i ako se nedetektuje usporenje voza. Ako detektuje da voz ne usporava nakonisteka tog roka, ovaj sistem treba da aktivira pomoćni kočioni sistem uroku od dodatnih t c = 0.2 s nakon tog roka t d .Softver ovog kontrolnog sistema implementiran je kao jedan periodičniproces koji je stalno aktivan i koji radi na sledeći način. Ako u nekojaktivaciji prvi put pronađe da je glavna kočnica aktivirana, ne radi ništa utoj i u još nekoliko narednih aktivacija (ukupno njih n), kako biobezbedio protok <strong>vreme</strong>na t d , a onda u n+1-oj aktivaciji, ukolikopronađe da voz i dalje ne usporava a glavna kočnica je još uvekaktivirana, aktivira rezervnu kočnicu.


Na raspolaganju su sledeće funkcije interfejsa premauređajima:◦ isMainBreakOn():Boolean• Vraća True ako je glavna kočnica aktivirana◦ isDecelerating():Boolean• Vraća True ako je detektovano usporenje voza◦ emergencyBreakOn()• Uključuje pomoćnu kočnicu.a) Na jeziku Ada implementirati ovaj proces tako dane pati od kumulativnog plivanja (engl. cumulativedrift), uzimajući periodu kao simboličku konstantu.b) Napisati i objasniti nejednakosti koje predstavljajuuslove za periodu (T), <strong>vreme</strong>nski rok (D) i brojaktivacija n u funkciji t d i t c , a potom odrediti oveparametre (T, D i n).

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!