Skripta PRV

Embed Size (px)

Citation preview

  • 7/31/2019 Skripta PRV

    1/299

    Dragan Miliev, Bojan Furlan

    Programiranje u realnom vremenu -

    Skripta sa praktikumom i reenim

    zadacima

    Univezitet u BeograduElektrotehniki fakultetBeograd, 2011

    Ovaj materijal je objavljen u okviru projekta WUS Austria MSDP 2011 finansiranog od strane Austrijske agencije za razvoj / The

    publishing of this material is part of the project MSDP 2011 financed by Austrian Development Agency through WUS Austria.

    Besplatan primerak / This copy is not for sale

  • 7/31/2019 Skripta PRV

    2/299

    Programiranje u realnom vremenu 2

    Dragan Miliev, Bojan Furlan

    Programiranje u realnom vremenu -Skripta sa praktikumom i reenim zadacima

    Recezenti

    dr Sanja Vranedr Vladimir Blagojevi

    Odlukom Nastavno-naunog vea Elektrotehnkog fakultetabroj 2093 od 18.10.2011. godine ovaj rukopis je odobren kao

    nastavni materijal na Elektrotehnikom fakultetu u Beogradu

    IzdavaElektrotehniki fakultet

    ISBN 978-86-7225-046-6

  • 7/31/2019 Skripta PRV

    3/299

    Programiranje u realnom vremenu 3

    Predgovor

    Ovaj rukopis je proizaao iz materjala sainjenih za predavanja i vebe za predmetProgramiranje u realnom vremenu koji se dugi niz godina dri na osnovnim i akademskimmaster studijama na Elektrotehnikom fakultetu u Beogradu. Nivo sloenosti i nain izlaganjapodrazumeva neophodno predznanje iz objektno orijentisanog programiranja, algoritama i

    struktura podataka, operativnih sistema, kao i konkurentnog i distribuiranog programiranja.

    U cilju boljeg i lakeg usvajanja izloene problematike, kao i potpunijeg sagledavanja ovesavremene inenenjerske oblasti izloeni su reeni problemi i zadaci koji su dati na krajusvake oblasti, a poslednje poglavlje predstavlja praktikum koji se odnosi na upotrebu jednog

    savremenog aplikativnog okruenja za modelovanje i razvoj sofrverskih sistema za rad urealnom vremenu.

    Skripta je prvenstveno namenjena studentima Elektrotehnikog fakulteta koji sluajupomenuti predmet na akademskim master studijama modula Softversko inenjerstvo iliRaunarska tehnika i informatika. Ona u potpunosti obuhvata gradivo predvieno za

    predavanja i vebe, kao i za laboratorijske vebe. Autori se nadaju da e tekst biti od koristi idrugim studentima, inenjerima i praktiarima koji imaju dodira sa ovom oblau.

    Na kraju, autori su svesni da i pored uloenog truda, ovaj materijal moe sadrati greke,stoga bie zahvalni za sve sugestije, korekcije i primedbe italaca.

    Beograd, maj 2011. Autori

  • 7/31/2019 Skripta PRV

    4/299

    Programiranje u realnom vremenu 4

    Sadraj

    Sadraj 1

    Predgovor 3

    I UVOD U SISTEME ZA RAD U REALNOM VREMENU 8

    Definicija sistema za rad u realnom vremenu 8Podela i terminologija RT sistema 8Primeri RT sistema 9

    Karakteristike RT sistema 10

    Primeri struktura pogodnih za RT implementacije 11

    II POUZDANOST I TOLERANCIJA OTKAZA 34

    Pouzdanost i tolerancija otkaza 35Pouzdanost, padovi i otkazi 35Spreavanje i tolerancija otkaza 36N-Version Programiranje 37Dinamika softverska redundansa 39Blokovi oporavka 42

    Izuzeci i njihova obrada 45Dinamika redundansa i izuzeci 45Obrada izuzetaka bez posebne jezike podrke 45Izuzeci i njihova reprezentacija 46Obrada izuzetka 48Propagacija izuzetka 49Zadaci 51Zadaci za samostalan rad 58

    III OSNOVE KONKURENTNOG PROGRAMIRANJA 60

    Konkurentnost i procesi 61Konkurentno programiranje 61Pojam procesa 63Predstavljanje procesa 65Interakcija izmeu procesa 68Implementacija niti 68Zadaci 86Zadaci za samostalan rad 87

    Sinhronizacija i komunikacija pomou deljene promenljive 89Meusobno iskljuenje i uslovna sinhronizacija 89Uposleno ekanje 91Semafori 94

    Uslovni kritini regioni 99Monitori 100Klasifikacija poziva operacija 106

  • 7/31/2019 Skripta PRV

    5/299

    Programiranje u realnom vremenu 5

    Implementacija sinhronizacionih primitiva 106Zadaci 111Zadaci za samostalan rad 118

    Sinhronizacija i komunikacija pomou poruka 119Sinhronizacija procesa 119

    Imenovanje procesa i struktura poruke 121Randevu u jeziku Ada 122Zadaci 125Zadaci za samostalan rad 126

    Kontrola resursa 127Modeli za pristup deljenim resursima 127Problemi nadmetanja za deljene resurse 129Zadaci za samostalan rad 136

    IV SPECIFINOSTI RT PROGRAMIRANJA 138

    Realno vreme 139asovnik realnog vremena 139Merenje proteklog vremena 142Vremenske kontrole 143Kanjenje procesa 147Specifikacija vremenskih zahteva 148Kontrola zadovoljenja vremenskih zahteva 152Implementacija u kolskom Jezgru 154Zadaci 164Zadaci za samostalan rad 180

    Rasporeivanje 188Osnovne strategije rasporeivanja 188Testovi rasporedivosti 192Optiji model procesa 198Projektovanje prema vremenskim zahtevima 205Zadaci 209Zadaci za samostalan rad 214

    V OSNOVE OBJEKTNO ORIJENTISANOG MODELOVANJA NA JEZIKUUML 217

    Modelovanje strukture 218Klasa, atributi i operacije 218

    Asocijacija 218Zavisnost 221Generalizacija/Specijalizacija 222Interfejsi 223

    Modelovanje ponaanja 224Interakcije i dijagrami interakcije 224Aktivnosti i dijagrami aktivnosti 226Maine stanja i dijagrami prelaza stanja 228

    Organizacija modela 234Paketi 234Dijagrami 234

    VI MODELOVANJE RT SISTEMA 236

  • 7/31/2019 Skripta PRV

    6/299

    Programiranje u realnom vremenu 6

    Uvod 237Istorijat 237Primenljivost 237Principi 237Demo primer aplikacije 238

    Jednostavan ROOM model 240Definicija interfejsa 240Definisanje ponaanja aktera 241Izvravanje modela 245

    Hijerarhijski model sa vie aktera 247Komunikacija izmeu aktera 247Sistemske servisne pristupne taake 252interne sekvence poruka 253Hijerarhijske maine stanja 254Izvravanje modela sa vie aktera 255

    Nivo detalja 257

    Nasleivanje 260

    Napredni koncepti 262

    VII PRAKTIKUM 265

    Rational Rose Technical Developer 266

    Podeavanje okruenja 267

    Postavka zadatka 268Pretpostavke 268

    Kreiranje modela 270Kreiranje novog modela 270Kreiranje use case dijagrama 272Kreiranje kapsula (aktora) 272Kreiranje dijagrama strukture za kapsule 273Kreiranje sturkture Alarm kapsule 273Kreiranje dijagrama sekvence 276Kreiranje protokola 276Kreiranje portova i konektora 277Dokumentovanje 279

    Dodavanje ponaanja kapsuli 279

    Kompajliranje i izvravanje 283Kreiranje komponente 283Kompajliranje 284Izvravanje 284Testiranje 287

    Proirenje modela 290Kreiranje timing porta 291Povezivanje portova 292Dodavanje atributa 293Kreiranje stanja 294

    Testiranje 295Kreiranje trace-a 297

  • 7/31/2019 Skripta PRV

    7/299

    Programiranje u realnom vremenu 7

    Samostalan rad 298Korisni linkovi 298

    Literatura 299

  • 7/31/2019 Skripta PRV

    8/299

  • 7/31/2019 Skripta PRV

    9/299

    Programiranje u realnom vremenu 9

    o "Tvrdi" (engl. hard): RT sistemi za koje je apsolutni imperativ da odziv stigneu zadatom roku (engl. deadline). Prekoraenje roka (engl. deadline miss) ilineisporuenje rezultata moe da dovede do katastrofalnih posledica na ivoteljudi, materijalna sredstva ili okolinu. Primeri: sistem za kontrolu nuklearne

    elektrane, sistem za upravljanje letom aviona itd.

    o "Meki" (engl. soft): RT sistemi kod kojih su rokovi vani, ali se povremenomogu i prekoraiti, sve dok performanse sistema (propusnost i kanjenje)statistiki ulaze u zadate okvire. Primeri: telefonska centrala, sistem zaprikupljanje podataka u industriji itd.

    Prema ovim definicijama, vane karakteristike RT sistema su sledee:o Za hard sisteme, bitno je teorijski dokazati njihovu izvodljivost (engl.

    feasibility), tj. pokazati da se zadati rokovi nee prekoraiti ni u kom sluaju,pri zadatim uslovima i resursima. Ova analiza izvodljivosti najeepodrazumeva analizu rasporedivosti (engl. schedulability) definisanih poslova

    na raspoloive procesne jedinice.

    o

    Za soft sisteme, bitno je teorijski, simlaciono ili praktino pokazati da superformanse (engl. performance) sistema zadovoljavajue, tj. u zadatimgranicama pod svim uslovima. To podrazumeva statistiku analizu (npr.srednje vrednosti i disperzije) parametara performansi, kao to su kanjenje(engl. delay) ili propusnost (engl. throughput).

    "Stvarnim" RT sistemom (engl. real real-time) se naziva hard RT sistem kod koga suvremenski rokovi apsolutno kratki (reda milisekundi).

    "Strogim" RT sistemom (engl. firm real-time) se naziva soft RT sistem kod koga jezakasneli odgovor beskoristan.

    Mnogi sistemi u praksi imaju vie svojih komponenata koje spadaju u razliite navedenekategorije. esto se za prekoraenje roka definie odgovarajua funkcija cene koju trebaminimizovati pri realizaciji sistema.

    Primeri RT sistema

    Sistemi za kontrolu procesa (engl. process control systems): upravljanje cevovodima,nameavanje supstanci, praenje sagorevanja, nadzor elektrine centrale itd.

    Sistemi za proizvodnju (engl. manufacturing systems): pokretna traka za sastavljanjedelova, maina za proizvodnju delova itd.

    Sistemi za komunikaciju, upravljanje i nadzor (engl. communication, command, andcontrol systems, CCC): kontrola leta, upravljanje inskim saobraajem, upravljanjeprojektilima, avionski sitem, komunikacioni sistemi itd.

    Telekomunikacioni sistemi: telefonska centrala (javna, kuna, za mobilnu telefoniju),mobilni telefon, komunikacioni ureaji (router, switch, itd.) itd.

    Razni ugraeni (engl. embedded) sistemi: medicinski sistemi i sl. Simulacioni sistemi: simulacija leta aviona, simulacija borbenih dejstava itd.

  • 7/31/2019 Skripta PRV

    10/299

    Programiranje u realnom vremenu 10

    Karakteristike RT sistema

    RT sistemi su najee vrlo veliki i kompleksni. Njihova funkcionalnost je sloena, aimplementacija moe da varira od nekoliko stotina linija asemblerskog ili C koda, sve dodesetak miliona linija koda nekog vieg programskog jezika. Teko je ili nemogue da takav sistem razume, napravi ili odrava jedna osoba.

    RT sistemi su najee konkurentni, jer to odgovara uporednom i kontinualnom deavanjupromena, procesa i dogaaja u realnom okruenju. Zbog toga i koncepti za RTprogramiranje treba da podre konkurentnost, jer je tako lake modelovati konkurentneprirodne procese nego pomou sekencijalnih koncepata.

    RT sistemi esto manipuliu racionalnim brojevima koji su numerike aproksimacijeveliina iz okruenja. Algoritmi ugraeni u RT softver moraju da uzmu u obzir ogranienu

    tanost ovih aproksimacija i mogunost neregularnih operacija. RT softver neposredno interaguje sa hardverom, pa je zato neophodno da programski jezikomoguuje programski pristup do posebnih hardverskih ureaja.

    RT sistemi vrlo esto moraju da budu ekstremno pouzdani i sigurni. Oni operiu urealnom okruenju pod razliitim uticajima koji mogu da dovedu do otkaza ilineispravnog funkcionisanja, a koje moe uzrokovati tetu ili ugroavanje ivota i okoline.

    RT sistemima se postavljaju zahtevi za garantovanim vremenom odziva. Potrebno je zatoimati sredstvo za pouzdanu predikciju najgoreg mogueg vremena izvravanja. Iako su

    performanse vane za soft sisteme, za hard sisteme je sutinski vana pouzdanapredvidivost ponaanja u vremenu.

    Varijante konfiguracije softvera za RT sisteme:

    Aplikacija

    Operativni

    sistem

    Hard

    ver

    Aplikacija i komponente

    OS-a

    Hardver

  • 7/31/2019 Skripta PRV

    11/299

    Programiranje u realnom vremenu 11

    Primeri struktura pogodnih za RTimplementacije

    Kolekcija implementirana kao dvostruko ulanana dinamika lista

    Koncepcija

    Za mnoge primene u RT i drugim sistemima potrebna je struktura koja predstavljakolekciju pokazivaa na objekte nekog tipa. Kolekcija je linearna struktura elemenata ukoju se elementi mogu ubacivati, iz koje se mogu izbacivati, i koji se mogu redom

    obilaziti. Jedna jednostavna implementacija oslanja se na dinamiku, dvostruko ulananu listu,iji

    su elementi strukture koje sadre veze (pokazivae) prema susednim elementima i samsadraj (pokaziva na objekat u kolekciji). Ove strukture se dinamiki alociraju idealociraju prilikom umetanja i izbacivanja elemenata.

    Implementacija

    // Project: Real-Time Programming// Subject: Data Structures// Module: Collection// File: collection.h// Date: October 2002

    // Author: Dragan Milicev// Contents:// Class: Collection// CollectionIterator

    #ifndef _COLLECTION_#define _COLLECTION_

    /////////////////////////////////////////////////////////////////////// class Collection/////////////////////////////////////////////////////////////////////

    class Object;class CollectionElement;

    class CollectionIterator;

    class Collection {public:

    Collection ();~Collection ();

    void append (Object*);void insert (Object*, int at=0);void remove (Object*);Object* remove (int at=0);Object* removeFirst() { return remove(0); }

    Object* removeLast() { return remove(size()-1); }void clear ();

  • 7/31/2019 Skripta PRV

    12/299

    Programiranje u realnom vremenu 12

    int isEmpty () { return sz==0; }int size () { return sz; }Object* first ();Object* last ();Object* itemAt (int at);int location(Object*);

    CollectionIterator* createIterator ();CollectionIterator* getIterator () { return internalIterator; }

    protected:

    void remove (CollectionElement*);

    private:

    friend class CollectionIterator;CollectionElement* head;CollectionElement* tail;int sz;

    CollectionIterator* internalIterator;

    };

    /////////////////////////////////////////////////////////////////////// class CollectionIterator/////////////////////////////////////////////////////////////////////

    class CollectionIterator {public:

    CollectionIterator (Collection* c) : col(c), cur(0) { reset(); }

    void reset() { if (col!=0) cur=col->head; }int next ();

    int isDone() { return cur==0; }Object* currentItem();

    private:

    Collection* col;CollectionElement* cur;

    };

    #endif

    // Project: Real-Time Programming// Subject: Data Structures// Module: Collection// File: collection.cpp// Date: October 2002// Author: Dragan Milicev// Contents:

    // Class: Collection// CollectionIterator

  • 7/31/2019 Skripta PRV

    13/299

    Programiranje u realnom vremenu 13

    #include "collection.h"

    /////////////////////////////////////////////////////////////////////// class CollectionElement/////////////////////////////////////////////////////////////////////

    class CollectionElement {

    public:Object* cont;CollectionElement *prev, *next;

    CollectionElement (Object*);CollectionElement (Object*, CollectionElement* next);CollectionElement (Object*, CollectionElement* prev, CollectionElement*

    next);};

    inline CollectionElement::CollectionElement (Object* e)

    : cont(e), prev(0), next(0) {}

    inline CollectionElement::CollectionElement (Object* e, CollectionElement*n)

    : cont(e), prev(0), next(n) {if (n!=0) n->prev=this;

    }

    inline CollectionElement::CollectionElement (Object* e, CollectionElement*p, CollectionElement* n)

    : cont(e), prev(p), next(n) {if (n!=0) n->prev=this;

    if (p!=0) p->next=this;}

    /////////////////////////////////////////////////////////////////////// class Collection/////////////////////////////////////////////////////////////////////

    Collection::Collection (): head(0), tail(0), sz(0),internalIterator(new CollectionIterator(this))

    {}

    Collection::~Collection () {clear();delete internalIterator;

    }

    void Collection::remove (CollectionElement* e) {if (e==0) return;if (e->next!=0) e->next->prev=e->prev;else tail=e->prev;if (e->prev!=0) e->prev->next=e->next;

    else head=e->next;if (internalIterator && internalIterator->currentItem()==e->cont)internalIterator->next();

  • 7/31/2019 Skripta PRV

    14/299

    Programiranje u realnom vremenu 14

    delete e;sz--;

    }

    void Collection::append (Object* e) {if (head==0) head=tail=new CollectionElement(e);

    else tail=new CollectionElement(e,tail,0);sz++;

    }

    void Collection::insert (Object* e, int at) {if (atsize()) return;if (at==0) {

    head=new CollectionElement(e,head);if (tail==0) tail=head;sz++;return;

    }if (at==size()) {

    append(e);return;

    }int i=0;for (CollectionElement* cur=head; inext, i++);new CollectionElement(e,cur->prev,cur);sz++;

    }

    void Collection::remove (Object* e) {if (tail && tail->cont==e) {

    remove(tail);return;

    }for (CollectionElement* cur=head; cur!=0; cur=cur->next)

    if (cur->cont==e) remove(cur);}

    Object* Collection::remove (int at) {Object* ret = 0;if (at=size()) return 0;if (at==0) {

    ret = head->cont;remove(head);return ret;

    }

    if (at==size()-1) {ret = tail->cont;remove(tail);return ret;

    }int i=0;for (CollectionElement* cur=head; inext, i++);ret = cur->cont;remove(cur);return ret;

    }

    void Collection::clear () {

    for (CollectionElement* cur=head, *temp=0; cur!=0; cur=temp) {temp=cur->next;delete cur;

  • 7/31/2019 Skripta PRV

    15/299

  • 7/31/2019 Skripta PRV

    16/299

    Programiranje u realnom vremenu 16

    };

    class X : public Object {public:

    X(int ii) : i(ii) {}int i;

    //...};

    void main () {X* x1 = new X(1);X* x2 = new X(2);X* x3 = new X(3);X* x4 = new X(4);X* x5 = new X(5);

    Collection* col1 = new Collection;col1->append(x1);col1->append(x2);

    col1->insert(x3);col1->insert(x4,2);X* x = (X*)col1->removeFirst();col1->append(x);col1->insert(x5,3);

    CollectionIterator* it = col1->getIterator();for (it->reset(); !it->isDone(); it->next()) {

    X* x = (X*)it->currentItem();coutappend(x5);it = col2->getIterator();for (it->reset(); !it->isDone(); it->next()) {

    X* x = (X*)it->currentItem();coutcurrentItem();coutisDone(); it->next()) {

    X* x = (X*)it->currentItem();cout

  • 7/31/2019 Skripta PRV

    17/299

    Programiranje u realnom vremenu 17

    delete col2;delete x1;delete x2;delete x3;delete x4;delete x5;

    }

    Analiza kompleksnosti

    Neka je kompleksnost algoritma alokacije prostora ugraenog alokatora (ugraeneoperatorske funkcije new) Ca, a algoritma dealokacije Cd. Neka je n veliina kolekcije(broj elemenata u kolekciji). Tada je kompleksnost najznaajnijih operacija prikazaneimplementacije sledea:

    Operacija KompleksnostCollection::append(Object*) CaCollection::insert(Object*) Ca

    Collection::insert(Object*,int) Ca+O(n)Collection::remove(Object*) Cd+O(n)Collection::remove(int) Cd+O(n)Collection::removeFirst() CdCollection::removeLast() CdCollection::clear() CdO(n)Collection::isEmpty() O(1)Collection::size() O(1)Collection::first() O(1)Collection::last() O(1)

    Collection::itemAt(int) O(n)Collection::location(Object*) O(n)CollectionIterator::reset() O(1)CollectionIterator::next() O(1)CollectionIterator::isDone() O(1)Collection::currentItem() O(1)

    Prema tome, najkritinije i najee koriene operacije za umetanje i izbacivanjeelemenata jako zavise od kompleksnosti algoritma ugraenog alokatora i dealokatora. U

    zavisnosti od implementacije struktura koje vode rauna o zauzetom i slobodnom prostoruu dinamikoj memoriji, ova kompleknost moe razliita. Tipino je to O(k), gde je kbrojzauzetih i/ili slobodnih segmenata dinamike memorije, ili u boljem sluaju O(log k). to

    je jo gore, operacija Collection::remove(Object*) ima i dodatnu kompleksnost O(n),zbog sekvencijalne pretrage elementa koji se izbacuje.

    Zbog ovakve orijentacije na ugraene alokatore, ija se kompleksnost teko moeproceniti i kontrolisati, kao i na sekvencijalnu pretragu kod izbacivanja, ova

    implementacija nije pogodna za RT sisteme.

    Kolekcija kao ulanana lista sa vezama ugraenim u objekte

    Koncepcija

  • 7/31/2019 Skripta PRV

    18/299

    Programiranje u realnom vremenu 18

    Problem sa prethodnim reenjem je to se za strukturu veza izmeu elemenatakolekcije alocira poseban prostor, na ta se troi vreme pri umetanju i izbacivanju elemenata.Osim toga, objekat koji je element kolekcije nema nikakvu vezu prema toj strukturi, pa je kod

    izbacivanja elementa (zadatog kao pokaziva na dati objekat) potrebno vriti sekvencijalnupretragu kolekcije.

    Reenje koje eliminie ove probleme oslanja se na to da struktura veza bude ugraenau same objekte koji se smetaju u kolekciju. Zbog toga nema potrebe za alokaciju idealokaciju struktura za veze.

    Potencijalni problem sa ovakvim pristupom je da moe doi do greke ukoliko seobjekat koji je ve element neke kolekcije pokua ubaciti u drugu kolekciju, korienjem istestrukture za veze, ime dolazi do koripcije prve kolekcije. Zato je u ovu implementacijuugraena zatita od ovakve pogrene upotrebe.

    Implementacija

    // Project: Real-Time Programming// Subject: Data Structures

    // Module: Collection// File: collect.h// Date: October 2002// Author: Dragan Milicev// Contents:// Class:// CollectionElement// Collection// CollectionIterator

    #ifndef _COLLECTION_#define _COLLECTION_

    /////////////////////////////////////////////////////////////////////

    // class CollectionElement/////////////////////////////////////////////////////////////////////

    class Object;class Collection;

    class CollectionElement {public:

    CollectionElement (Object* holder);

    Object* getHolder() { return holder; }Collection* getContainer () { return container; }

    private:

    friend class Collection;friend class CollectionIterator;void set (CollectionElement* prev, CollectionElement* next);void setContainer (Collection* col) { container = col; }

    CollectionElement *prev, *next;

    Collection* container;Object* holder;

    };

  • 7/31/2019 Skripta PRV

    19/299

    Programiranje u realnom vremenu 19

    inline CollectionElement::CollectionElement (Object* h): container(0), holder(h), prev(0), next(0) {}

    inline void CollectionElement::set (CollectionElement* p,CollectionElement* n) {

    prev = p;next = n;if (n!=0) n->prev=this;if (p!=0) p->next=this;

    }

    /////////////////////////////////////////////////////////////////////// class Collection/////////////////////////////////////////////////////////////////////

    class CollectionIterator;

    class Collection {public:

    Collection ();~Collection ();

    void append (CollectionElement*);void insert (CollectionElement*, int at=0);void insertBefore (CollectionElement* newElem, CollectionElement*

    beforeThis);void insertAfter (CollectionElement* newElem, CollectionElement*

    afterThis);

    void remove (CollectionElement*);Object* remove (int at=0);Object* removeFirst() { return remove(0); }Object* removeLast() { return remove(size()-1); }

    void clear ();

    int isEmpty () { return sz==0; }int size () { return sz; }

    Object* first () { return head->getHolder(); }Object* last () { return tail->getHolder(); }Object* itemAt (int at);

    int location(CollectionElement*);

    CollectionIterator* createIterator ();CollectionIterator* getIterator () { return internalIterator; }

    private:

    friend class CollectionIterator;CollectionElement* head;CollectionElement* tail;int sz;

    CollectionIterator* internalIterator;

    };

  • 7/31/2019 Skripta PRV

    20/299

    Programiranje u realnom vremenu 20

    /////////////////////////////////////////////////////////////////////// class CollectionIterator/////////////////////////////////////////////////////////////////////

    class CollectionIterator {public:

    CollectionIterator (Collection* c) : col(c), cur(0) { reset(); }

    void reset() { if (col!=0) cur=col->head; }int next () { if (cur!=0) cur=cur->next; return !isDone(); }

    int isDone() { return cur==0; }

    Object* currentItem() { return cur?cur->getHolder():0; }CollectionElement* currentElement() { return cur; }

    private:

    Collection* col;CollectionElement* cur;

    };

    #endif

    // Project: Real-Time Programming// Subject: Data Structures// Module: Collection// File: collect.cpp// Date: October 2002// Author: Dragan Milicev// Contents:// Class: CollectionElement// Collection// CollectionIterator

    #include "collect.h"

    /////////////////////////////////////////////////////////////////////// class Collection/////////////////////////////////////////////////////////////////////

    Collection::Collection (): head(0), tail(0), sz(0),internalIterator(new CollectionIterator(this))

    {}

    Collection::~Collection () {clear();delete internalIterator;

    }

    void Collection::append (CollectionElement* e) {if (e==0 || e->getContainer()!=0) return;

  • 7/31/2019 Skripta PRV

    21/299

    Programiranje u realnom vremenu 21

    if (head==0) {e->set(0,0);head=tail=e;

    }else {

    e->set(tail,0);tail=e;

    }e->setContainer(this);sz++;

    }

    void Collection::insert (CollectionElement* e, int at) {if (e==0 || e->getContainer()!=0 || atsize()) return;if (at==0) {

    e->set(0,head);e->setContainer(this);head=e;if (tail==0) tail=head;sz++;

    return;}if (at==size()) {

    append(e);return;

    }int i=0;for (CollectionElement* cur=head; inext, i++);e->set(cur->prev,cur);e->setContainer(this);sz++;

    }

    void Collection::insertBefore (CollectionElement* newElem,CollectionElement* beforeThis) {

    if (newElem==0 || newElem->getContainer()!=0) return;if (beforeThis==0) { append(newElem); return; }if (beforeThis->prev==0) { insert(newElem); return; }newElem->set(beforeThis->prev,beforeThis);newElem->setContainer(this);sz++;

    }

    void Collection::insertAfter (CollectionElement* newElem,CollectionElement* afterThis) {

    if (newElem==0 || newElem->getContainer()!=0) return;

    if (afterThis==0) { insert(newElem); return; }if (afterThis->next==0) { append(newElem); return; }newElem->set(afterThis,afterThis->next);newElem->setContainer(this);sz++;

    }

    void Collection::remove (CollectionElement* e) {if (e==0 || e->getContainer()!=this) return;if (e->next!=0) e->next->prev=e->prev;else tail=e->prev;if (e->prev!=0) e->prev->next=e->next;else head=e->next;

    e->set(0,0);e->setContainer(0);if (internalIterator && internalIterator->currentItem()==e->getHolder())

  • 7/31/2019 Skripta PRV

    22/299

    Programiranje u realnom vremenu 22

    internalIterator->next();sz--;

    }

    Object* Collection::remove (int at) {CollectionElement* ret = 0;

    if (at=size()) return 0;if (at==0) {

    ret = head;remove(head);return ret?ret->getHolder():0;

    }if (at==size()-1) {

    ret = tail;remove(tail);return ret?ret->getHolder():0;

    }int i=0;for (CollectionElement* cur=head; inext, i++);ret = cur;

    remove(cur);return ret?ret->getHolder():0;

    }

    void Collection::clear () {for (CollectionElement* cur=head, *temp=0; cur!=0; cur=temp) {

    temp=cur->next;cur->set(0,0);

    cur->setContainer(0);}head=0;tail=0;sz=0;

    if (internalIterator) internalIterator->reset();}

    Object* Collection::itemAt (int at) {if (at=size()) return 0;int i=0;for (CollectionElement* cur=head; inext, i++);return cur?cur->getHolder():0;

    }

    int Collection::location (CollectionElement* e) {if (e==0 || e->getContainer()!=this) return -1;

    int i=0;for (CollectionElement* cur=head; cur!=0; cur=cur->next, i++)

    if (cur==e) return i;return -1;

    }

    CollectionIterator* Collection::createIterator () {return new CollectionIterator(this);

    }

    Primer upotrebe

    #include "collect.h"

    #include

    class Object {

  • 7/31/2019 Skripta PRV

    23/299

    Programiranje u realnom vremenu 23

    //...};

    class X : public Object {public:

    X(int ii) : i(ii), ceForC1(this), ceForC2(this) {}

    int i;

    CollectionElement ceForC1;CollectionElement ceForC2;//...

    };

    void main () {X* x1 = new X(1);X* x2 = new X(2);X* x3 = new X(3);X* x4 = new X(4);X* x5 = new X(5);

    Collection* col1 = new Collection;col1->append(&x1->ceForC1);col1->append(&x2->ceForC1);col1->insert(&x3->ceForC1);col1->insert(&x4->ceForC1,2);X* x = (X*)col1->removeFirst();col1->append(&x->ceForC1);col1->insert(&x5->ceForC1,3);

    CollectionIterator* it = col1->getIterator();for (it->reset(); !it->isDone(); it->next()) {

    X* x = (X*)it->currentItem();coutappend(&x3->ceForC2);col2->append(&x4->ceForC2);col2->append(&x5->ceForC2);col2->append(&x3->ceForC1); // Tolerant Errorit = col2->getIterator();for (it->reset(); !it->isDone(); it->next()) {

    X* x = (X*)it->currentItem();coutcurrentItem();coutisDone(); it->next()) {

    X* x = (X*)it->currentItem();cout

  • 7/31/2019 Skripta PRV

    24/299

    Programiranje u realnom vremenu 24

    col1->clear();delete col1;col2->clear();delete col2;delete x1;

    delete x2;delete x3;delete x4;delete x5;

    }

    Analiza kompleksnosti

    Kompleksnost ove implementacije vie ne zavisi od kompleksnosti algoritma alokatora idealokatora. Kompleksnost najznaajnijih operacija je sada znaajno smanjena, naroitoza najee operacije stavljanja i izbacivanja elementa, i to na poetak ili kraj:

    Operacija Kompleksnost

    Collection::append(CollectionElement*) O(1)Collection::insert(CollectionElement*) O(1)Collection::insert(CollectionElement*,int) O(n)Collection::insertBefore(...) O(1)Collection::insertAfter(...) O(1)Collection::remove(CollectionElement*) O(1)Collection::remove(int) O(n)Collection::removeFirst() O(1)Collection::removeLast() O(1)Collection::clear() O(n)

    Collection::isEmpty() O(1)Collection::size() O(1)Collection::first() O(1)Collection::last() O(1)Collection::itemAt(int) O(n)Collection::location(CollectionElement*) O(n)CollectionIterator::reset() O(1)CollectionIterator::next() O(1)CollectionIterator::isDone() O(1)Collection::currentItem() O(1)

    Collection::currentElement() O(1)

    FIFO Red

    Koncepcija

    FIFO (First-In First-Out) red (engl. queue) je struktura u koju se elementi mogu umetati ivaditi, ali sa sledeim protokolom: operacija vaenja elementa uvek vraa element koji jenajdavnije stavljen u red, tako da se elementi vade po redosledu stavljanja.

    Implementacija

  • 7/31/2019 Skripta PRV

    25/299

    Programiranje u realnom vremenu 25

    Implementacija se u potrpunosti oslanja na realizovanu kolekciju:// Project: Real-Time Programming// Subject: Data Structures// Module: FIFO Queue// File: queue.h// Date: October 2002// Author: Dragan Milicev// Contents:// Class:// Queue

    #ifndef _QUEUE_#define _QUEUE_

    #include "collect.h"

    /////////////////////////////////////////////////////////////////////// class Queue/////////////////////////////////////////////////////////////////////

    class Queue {public:

    void put (CollectionElement* e) { col.append(e); }Object* get () { return col.removeFirst(); }void clear () { col.clear(); }

    int isEmpty () { return col.isEmpty(); }int isFull () { return 0; }int size () { return col.size(); }

    Object* first () { return col.first(); }Object* last () { return col.last(); }Object* itemAt (int at) { return col.itemAt(at); }

    int location(CollectionElement* e) { return col.location(e); }

    CollectionIterator* createIterator () { return col.createIterator(); }CollectionIterator* getIterator () { return col.getIterator(); }

    private:

    Collection col;

    };

    #endif

    Primer upotrebe

    Najee upotrebljavane operacije ove apstrakcije su operacije stavljanja (put()) iuzimanja elementa (get()). Data klasa koristi se slino kao i ranije realizovana kolekcija.

    Analiza kompleksnosti

    Kako se sve operacije ove klase svode na odgovarajue operacije klase Collection, timeje i njihova kompleksnost identina. Treba uoiti da je kompleksnost najee korienihoperacija put() i get() jednaka O(1).

  • 7/31/2019 Skripta PRV

    26/299

    Programiranje u realnom vremenu 26

    Red sa prioritetom

    Koncepcija

    Red sa prioritetom (engl. priority queue) je linearna struktura u koju se elementi mogusmetati i izbacivati, ali pri emu elementi imaju svojeprioritete. Prioritet je veliina kojase moe uporeivati (tj. za koju je definisana neka relacija totalnog ureenja, na primerprirodan broj).

    Najkritinije operacije ove strukture su operacije smetanja i izbacivanja elementa ioperacija vraanja (bez izbacivanja) elementa koji ima trenutno najvii prioritet.

    Implementacija

    Implementacija se oslanja na postojeu implementaciju kolekcije. Da bi kompleksnost obe operacije vraanja trenutno najprioritetnijeg elementa i operacije

    umetanja elementa bila manja od O(n), potrebno je da nijedna od njih ne ukljuuje

    linearnu pretragu po eventualno ureenoj listi. Zbog toga ova implementacija sadripokaziva na trenutno najprioritetniji element, koji se aurira prilikom promene strukturereda ili promene prioriteta nekog elementa.

    // Project: Real-Time Programming// Subject: Data Structures// Module: Priority Queue// File: pqueue.h// Date: October 2002// Author: Dragan Milicev// Contents:// Class:// PriorityElement

    // PriorityQueue// Type:// Priority

    #ifndef _PQUEUE_#define _PQUEUE_

    #include "collect.h"

    /////////////////////////////////////////////////////////////////////// class PriorityElement/////////////////////////////////////////////////////////////////////

    typedef unsigned int Priority;

    const Priority MinPri = 0;

    class PriorityQueue;

    class PriorityElement : public CollectionElement {public:

    PriorityElement (Object* holder, Priority p = 0): CollectionElement(holder), pri(p), container(0) {}

    Priority getPriority () { return pri; }void setPriority (Priority newPri);

    PriorityQueue* getContainer () { return container; }

  • 7/31/2019 Skripta PRV

    27/299

    Programiranje u realnom vremenu 27

    private:

    Priority pri;

    friend class PriorityQueue;void setContainer (PriorityQueue* c) { container = c; }PriorityQueue* container;

    };

    /////////////////////////////////////////////////////////////////////// class PriorityQueue/////////////////////////////////////////////////////////////////////

    class PriorityQueue {public:

    PriorityQueue () : col(), highest(0) {}

    Object* first () { return highest?highest->getHolder():0; }

    void add (PriorityElement*);void remove(PriorityElement*);void clear ();

    void notifyPriorityChange (PriorityElement*);

    int isEmpty () { return col.isEmpty(); }int size () { return col.size(); }

    CollectionIterator* createIterator () { return col.createIterator(); }

    CollectionIterator* getIterator () { return col.getIterator(); }

    private:

    Collection col;PriorityElement* highest;

    };

    #endif

    // Project: Real-Time Programming// Subject: Data Structures

    // Module: Priority Queue// File: pqueue.cpp// Date: October 2002// Author: Dragan Milicev// Contents:// Class:// PriorityElement// PriorityQueue

    #include "pqueue.h"

    /////////////////////////////////////////////////////////////////////// class PriorityElement/////////////////////////////////////////////////////////////////////

    void PriorityElement::setPriority (Priority newPri) {if (pri==newPri) return;

  • 7/31/2019 Skripta PRV

    28/299

    Programiranje u realnom vremenu 28

    pri = newPri;if (container!=0) container->notifyPriorityChange(this);

    }

    /////////////////////////////////////////////////////////////////////// class PriorityQueue/////////////////////////////////////////////////////////////////////

    void PriorityQueue::add (PriorityElement* e) {if (e==0 || e->getContainer()!=0) return;col.append(e);e->setContainer(this);notifyPriorityChange(e);

    }

    void PriorityQueue::remove(PriorityElement* e) {

    if (e==0 || e->getContainer()!=this) return;col.remove(e);e->setContainer(0);if (highest!=e) return;

    Priority maxPri = MinPri;highest = 0;CollectionIterator* it = getIterator();for (it->reset(); !it->isDone(); it->next()) {

    PriorityElement* pe = (PriorityElement*)it->currentElement();if (pe->getPriority()>=maxPri) {

    maxPri = pe->getPriority();highest = pe;

    }

    }}

    void PriorityQueue::clear () {CollectionIterator* it = getIterator();for (it->reset(); !it->isDone(); it->next()) {

    PriorityElement* pe = (PriorityElement*)it->currentElement();pe->setContainer(0);

    }col.clear();highest = 0;

    }

    void PriorityQueue::notifyPriorityChange (PriorityElement* e) {if (e==0 || e->getContainer()!=this) return;if (highest==0 || highest->getPriority()getPriority()) {

    highest = e;return;

    }if (highest==e) {

    Priority maxPri = e->getPriority();CollectionIterator* it = getIterator();for (it->reset(); !it->isDone(); it->next()) {

    PriorityElement* pe = (PriorityElement*)it->currentElement();

    if (pe->getPriority()>maxPri) {

    maxPri = pe->getPriority();highest = pe;}

  • 7/31/2019 Skripta PRV

    29/299

    Programiranje u realnom vremenu 29

    }return;

    }}

    Primer upotrebe

    #include "pqueue.h"#include

    class Object {//...

    };

    class X : public Object {public:

    X(int ID, Priority pri) : id(ID), peForPQ(this) {peForPQ.setPriority(pri); }

    int id;

    PriorityElement* getPriorityElement () { return &peForPQ; }

    Priority getPriority () { return peForPQ.getPriority();}

    void setPriority (Priority pri) { peForPQ.setPriority(pri); }

    private:

    PriorityElement peForPQ;

    //...};

    void main () {X* x1 = new X(1,1);X* x2 = new X(2,2);X* x3 = new X(3,3);X* x4 = new X(4,4);X* x5 = new X(5,5);

    PriorityQueue* pq = new PriorityQueue;pq->add(x1->getPriorityElement());pq->add(x3->getPriorityElement());pq->add(x4->getPriorityElement());pq->add(x2->getPriorityElement());pq->add(x5->getPriorityElement());

    X* top = 0;

    top = (X*)pq->first();cout

  • 7/31/2019 Skripta PRV

    30/299

    Programiranje u realnom vremenu 30

    cout

  • 7/31/2019 Skripta PRV

    31/299

    Programiranje u realnom vremenu 31

    Implementacija

    // Project: Real-Time Programming// Subject: Data Structures// Module: Recycle Bin// File: recycle.h// Date: October 2002

    // Author: Dragan Milicev// Contents:// Class:// RecycleBin// Macro:// RECYCLE_DEC(X)// RECYCLE_DEF(X)// RECYCLE_CON(X)

    #ifndef _RECYCLE_#define _RECYCLE_

    #include #include "collect.h"

    /////////////////////////////////////////////////////////////////////// class RecycleBin/////////////////////////////////////////////////////////////////////

    class RecycleBin {public:

    void recycle (CollectionElement* e) { col.append(e); }void* getNew (size_t size);

    int isEmpty () { return col.isEmpty(); }int size () { return col.size(); }

    private:

    Collection col;

    };

    /////////////////////////////////////////////////////////////////////// macro RECYCLE_DEC(X)/////////////////////////////////////////////////////////////////////

    #define RECYCLE_DEC(X) \private: static RecycleBin myRecycleBin; \public: static void* operator new (size_t); \public: static void operator delete (void*); \private: CollectionElement forRecycleBin;

    /////////////////////////////////////////////////////////////////////// macro RECYCLE_CON/////////////////////////////////////////////////////////////////////

    #define RECYCLE_CON(X) \

    forRecycleBin(this)

  • 7/31/2019 Skripta PRV

    32/299

    Programiranje u realnom vremenu 32

    /////////////////////////////////////////////////////////////////////// macro RECYCLE_DEF(X)/////////////////////////////////////////////////////////////////////

    #define RECYCLE_DEF(X) \

    RecycleBin X::myRecycleBin; \\void* X::operator new (size_t sz) { \

    return myRecycleBin.getNew(sz); \} \\void X::operator delete (void* p) { \

    myRecycleBin.recycle(&((X*)p)->forRecycleBin); \}

    #endif// Project: Real-Time Programming// Subject: Data Structures

    // Module: Recycle Bin// File: recycle.cpp// Date: October 2002// Author: Dragan Milicev// Contents:// Class:// RecycleBin

    #include "recycle.h"

    /////////////////////////////////////////////////////////////////////// class RecycleBin/////////////////////////////////////////////////////////////////////

    void* RecycleBin::getNew (size_t size) {Object* obj = col.removeFirst();if (obj!=0) return obj;return new char[size];

    }

    Primer upotrebe

    #include "recycle.h"

    class Object {};

    class Y : public Object {public:

    Y() : RECYCLE_CON(Y) {}int i,j,k;RECYCLE_DEC(Y)

    };

    // To be put into a .cpp file:RECYCLE_DEF(Y);

    void main () {Y* p1 = new Y;Y* p2 = new Y;delete p1;

    Y* p3 = new Y;delete p3;delete p2;

  • 7/31/2019 Skripta PRV

    33/299

    Programiranje u realnom vremenu 33

    }

    Analiza kompleksnosti

    Implementacija klase RecycleBin se oslanja na implementaciju kolekcije. U veinisluajeva, posle dovoljno dugog rada programa i ulaska u stacionarni reim kreiranja i

    unitavanja dinamikih objekata neke klase, logino je oekivati da se alokacija objektasvodi na uzimanje elementa iz kolekcije, to je izuzetno efikasno. U najgorem sluaju,alokacija se svodi na ugraeni algoritam alokatora. Dealokacija se u svakom sluaju svodina ubacivanje elementa u kolekciju:

    Operacija Kompleksnost u

    najeem sluaju

    Kompleksnost u najgorem

    sluajuX::new()/ RecycleBin::getNew() O(1) CaX::delete() / RecycleBin::recycle() O(1) O(1)

  • 7/31/2019 Skripta PRV

    34/299

    Programiranje u realnom vremenu 34

    I Pouzdanost itolerancija otkaza

  • 7/31/2019 Skripta PRV

    35/299

    Programiranje u realnom vremenu 35

    Pouzdanost i tolerancija otkaza

    Zahtevi za pouzdanost i sigurnost RT sistema su obino mnogo stroiji nego za drugeaplikacije. Na primer, ako doe do greke u radu nekog prorgama za naunaizraunavanja, izvravanje tog programa moe jednostavno da se prekine. Sa druge strane,sistem koji kontrolie neki industrijski proces, npr. neku veliku pe, ne sme sebi dadozvoli da prestane da radi zbog greke. Umesto toga, on treba da nastavi da radi saeventualno degradiranom funkcionalnou, ili da preduzme skupu i komplikovanu, alikontrolisanu operaciju gaenja pei. Ne treba ni naglaavati vanost optornosti na otkazesistema koji mogu da ugroze ivote u sluaju pada, npr. sistem za kontrolu leta ilinuklearne centrale.

    Izvori greaka u izvravanju programa su:o

    Neadekvatna specifikacija softverao Greke u realizaciji softverskih komponenata

    o Otkazi procesorskih komponenata u sistemuo Tranzientni ili permanentni uticaji na komunikacioni podsistem.

    Pouzdanost, padovi i otkazi

    Pouzdanost (engl. reliability) je mera uspenosti kojom se sistem pridrava autoritativnespecifikacije svog ponaanja. Ta specifikacija bi, u idealnom sluaju, trebalo da budekompletna, konzistentna, razumljiva i nedvosmislena. Vaan deo te specifikacije su

    vremena odziva. Pad(engl.failure) je sluaj kada ponaanje sistema odstupa od navedene specifikacije. Padovi su eksterne manifestacije u ponaanju prouzrokovane internim grekama (engl.

    error) u sistemu. Mehaniki ili algoritamski uzroci greaka nazivaju se otkazi (engl.fault). Sloeni sistemi se sastoje iz komponenata koje su opet sloeni sistemi. Zbog toga se otkaz

    u jednom podsistemu manifestuje kao greka, ova kao pad tog podsistema, a to opet kaootkaz na viem nivou hijerarhije itd.

    Vrste otkaza su:o Tranzientni otkazi (engl. transient faults) su otkazi koji nastaju u nekom trenutku,

    postoje u sistemu i onda nestaju posle nekog vremena. Primer je otkaz hardverske

    komponente koja reaguje na prisutnost spoljanjeg elektromagnetskog zraenja.Kada uzrok otkaza nestane, nestaje i greka.o Permanentni otkazi (engl. permanent faults) su otkazi koji nastaju u nekom

    trenutku i ostaju prisutni u sistemu sve dok se ne uklone popravkom sistema.

    Primeri: prekinuta ica ili greka u softveru.o Intermitentni otkazi (engl. intermittent faults) su tranzientni otkazi koji se deavaju

    s vremena na vreme. Primer je hardverska komponenta koja je osetljiva na

    zagrevanje; ona radi neko vreme i kada se zagreje, iskljui se, zatim se ohladi iponovo ukljui itd.

  • 7/31/2019 Skripta PRV

    36/299

    Programiranje u realnom vremenu 36

    Spreavanje i tolerancija otkaza

    Dva osnovna pristupa poveanju pouzdanosti su spreavanje i tolerancija otkaza. Spreavanje otkaza (engl. fault prevention) pokuava da eliminie svaku mogunost

    pojave otkaza sistema i pre nego to on postane operativan.

    Tolerancija otkaza (engl.fault tolerance) omoguava da sistem nastavi da funkcionie i uprisustvu otkaza.

    Spreavanje otkaza

    Dva stepena spreavanja otkaza: izbegavanje otkaza (engl. fault avoidance) i otklanjanjeotkaza (engl.fault removal).

    Izbegavanje otkaza tei da ogranii unoenje otkaza tokom konstrukcije samog sistemapomou:

    o korienja najpouzdanijih komponenata u okviru datih ogranienja u pogledu cenei performansio korienje preciznih i pouzdanih tehnika za interkonekciju komponenata isklapanje podsistema

    o pakovanje hardvera tako dabude zatien od spoljanjih tetnih uticajao rigorozna, ako ne i formalna specifikacija zahteva, upotreba dokazanih metoda

    projektovanja softvera i jezika koji podravaju apstrakciju i modularnosto upotreba alata za softversko inenjerstvo kao pomo za manipulisanje sloenim

    softverskim komponentama.

    Uprkos svim ovim naporima, greke u dizajnu i hardvera i softvera uvek e biti mogue. Otklanjanje otkaza podrazumeva procedure za pronalaenje a zatim i uklanjanje greaka u

    hardveru i softveru. Te procedure su, npr. pregled projekta, pregled koda (engl. code

    review), verifikacija programa i testiranje sistema.

    Testiranje sistema nikada ne moe biti potpuno iscrpno da eliminie sve greke zato to:o test nikada ne moe da dokae da greaka nema, nego samo da ih imao RT sisteme je esto nemogue testirati u realnim uslovimao veina testova se vri na sistemu koji radi u simulacionom reimu, a teko je

    garantovati da je simulacija adekvatna realnim uslovima

    o greke uzrokovane pogrenom specifikacijom zahteva se ne mogu manifestovatisve dok sistem ne postane operativan.

    I pored upotrebe svih tehnika softverske verifikacije i testiranja, hardverske komponentee otkazivati u radu, pa je pristup spreavanja otkaza neuspean jer:

    o uestanost ili trajanje popravki nije prihvatljivo, ilio sistem prosto nije fiziki dostupan za pronalaenje i uklanjanje otkaza (npr.bespilotna svemirska letilica).

    Zbog svega toga, uspenija alternativa je tolerancija otkaza (engl.fault tolerance).Tolerancija otkaza

    Tolerancija otkaza (engl.fault tolerance) omoguava da sistem nastavi da funkcionie i uprisustvu otkaza.

    Sve tehnike tolerancije otkaza zasnivaju se na ekstra elementima koji su uvedeni u sistemradi detekcije i oporavka od otkaza redundansa (engl. redundancy). Ovi elementi ne bibili potrebni u idealnom sistemu.

  • 7/31/2019 Skripta PRV

    37/299

    Programiranje u realnom vremenu 37

    Cilj je minimizovati redundansu a maksimizovati pouzdanost, pod zadatim ogranienjimau pogledu performansi i cene. Dodatno unete komponente obino negativno utiu naperformanse i cenu sistema.

    Pristupi u hardverskoj redudansi: statika i dinamika redundansa. Statika redundansa podrazumeva da su u konstrukciju sistema uvedene dodatne

    hardverske komponente koje treba da sakriju efekte greaka. Najpoznatiji primer statike redundanse je tzv. Trostruko Modularna Redundansa (engl.

    triple modular redundancy, TMR), ili u optem sluaju N-Modularna Redundansa: tri (iliN) identine komponente rade nezavisno i proizvode svaka svoj rezultat; posebnakomponenta uporeuje rezultate i usvaja onaj veinski, ukoliko se rezultati razlikuju;rezultat koji odstupa se odbacuje. Ovaj pristup pretpostavlja da greka nije zajednika(npr. greka u dizajnu) nego je npr. tranzijentna. Uoavanje greaka iz vie od jednekomponente zahteva NMR.

    Dinamika redundansa se ugrauje u komponentu tako da ukazuje da postoji greka unjenom rezultatu. Ova redundansa obezbeuje samo detekciju greke, dok otklanjanje

    greke mora da obezedi druga komponenta. Primeri: kontrolne sume (engl. checksums) priprenosu podataka ili bitovi parnosti u memorijskim elijama. Softverska redundansa:

    o Statika:N-Version programiranjeo Dinamika: detekcija greke, oporavak od greke unazad (engl. backward error

    recovery) i oporavak od greke unapred(engl.forward error recovery).

    N-Version Programiranje

    Uspeh tehnika statike redundanse u hardveru (TMR i NMR) inspirisalo je upotrebuslinih pristupa i za reavanje problema otkaza u softveru. Meutim, razlika je u tome tose softver ne haba i ne troi tokom upotrebe, pa je njegovo ponaanje nepromenjeno, ve

    je osnovni uzrok njegovorg otkaza nastao tokom njegove realizacije, a ne eksploatacije.

    Zbog toga se osnovna ideja N-version programiranja zasnova na nezavisnoj realizacijiN(gde je N2) funkcionalno ekvivalentnih verzija programa iz iste poetne specifikacije.Nezavisna realizacija N programa podrazumeva da N pojedinaca ili grupa proizvodi N

    verzija softvera bezmeusobnog uticaja (interakcije). Zbog toga se ovaj pristup naziva iraznolikost dizajna (engl. design diversity).

    Kada se napravi Nverzija programa, ti programi se izvravaju uporedo, sa istim ulaznimpodacima, dok njihove izlazne rezultate uporeuje tzv. driverproces. U principu, rezultati

    bi trebalo da budu identini. Ukoliko postoji razlika, usvaja se veinski, pod uslovom datakav postoji.

    Version 1

    Driver

    Version 2 Version 3

    vote

    vote

    votestatus

    status

    status

    N-versionprogramiranje se oslanja na pretpostavku da se program moe u potpunosti,konzistentno i nedvosmisleno specifikovati, kao i da programi koji su razvijeni nezavisno

  • 7/31/2019 Skripta PRV

    38/299

    Programiranje u realnom vremenu 38

    i otkazuju nezavisno. Drugim reima, da ne postoje korelacije izmeu greaka u nezavisnorazvijenim programima.

    Ovo obino podrazumeva realizaciju programa u razliitim programskim jezicima, i/ili urazliitim okruenjima (prevodioci, biblioteke, izvrna okruenja itd.).

    Driverproces ima zadatak da: (a) proziva svaku od verzija, (b) eka na sve rezultate i (c)uporeuje rezultate i donosi odluku. Ukoliko postoje razlike u rezultatu, driver procesmoe da donese odluku da nastavi sve procese, da neki od njih prekine, ili da promeni

    jednu ili vie manjinskih rezultata u veinski. Problem u odluivanju moe da bude poreenje rezultata razliitih verzija. Naime, ukoliko

    su rezultati npr. celobrojni ili stringovi (nizovi znakova), rezultati mogu i treba da budu

    identini. Meutim, ukoliko su rezultati realni brojevi, njihove racionalne aproksimacijemogu da budu razliite u razliitim verzijama, a da ipak sve budu korektne.

    Zbog toga je u nekim sluajevima potrebno neegzaktno glasanje (engl. inexact voting).Jedno jednostavno reenje je da se u takvim sluajevima izraunava srednja vrednostrazliitih rezultata i odstupanje svakog od te srednje vrednosti, pri emu se definie

    maksimalna granica tog odstupanja. Problem kod neegzaktnog glasanja moe da bude i tzv. problem nekonzistentnog

    poreenja (engl. inconsistent comparison problem), kada aplikacija treba da donosi

    odluke na osnovu zaokruenih rezultata. Na primer, sledee tri verzije programa kojikontrolie temperaturu i pritisak u odnosu na granine zadate vrednosti, zbog tri priblinevrednosti koje su sve razliite, ali blizu praga, donose tri razliite odluke, pri emu se svemogu smatrati ispravnim:

    T1 > Tth

    P1 > Pth

    Yes

    Yes

    V1

    T2 > Tth

    P2 > Pth

    Yes

    V2

    T3 > Tth

    V3

    No

    No

    Problemi mogu da nastanu i kod neegzatnog poreenja, jer se vrednosti mogu opet nalaziti

    blizu praga tolerancije. Slino, postoje problemi kod kojih postoji vie tanih reenja (npr.reenje kvadratne jednaine).

    UspehN-versionprogramiranja jako zavisi od sledeih inilaca:o Inicijalna specifikacija. Veina greaka u softveru jeste posledica neadekvatne

    specifikacije. Greka u specifikaciji e se manifestovati u svih N verzijaimplementacije.

  • 7/31/2019 Skripta PRV

    39/299

    Programiranje u realnom vremenu 39

    o Nezavisnost realizacije. Eksperimenti koji su imali zadatak da provere hipotezu onezavisnosti otkaza nezavisno realizovanih programa dali su konfliktne rezultate.

    Osim toga, u sluaju kada je neki deo specifikacije sloen, postoji velikaverovatnoa da e on dovesti do nerazumevanja zahteva. U tom sluaju e sverealizacije biti pogrene. Ako se pri tom deo odnosi na ulazne podatke koji se retko

    pojavljuju, testiranje sistema e verovatno propustiti da uoi zajednike greke urealizaciji.

    o Adekvatan budet. Dominantan troak u razvoju RT sistema je razvoj softvera.Ukoliko se realizuje program u npr. tri verzije, postavlja se pitanje da li se trostruki

    troak razvoja isplati i da li se on vie isplati nego trostruka investicija upouzdaniji razvoj jedne verzije (rigoroznije metode razvoja i testiranja).

    Zbog svega ovoga, iako N-versionprogramiranje moe znaajno da doprinese poveanjupouzdanosti sistema, treba ga upotrebljavati paljivo i samo u sluajevima visokih zahtevaza pouzdanou, i to u saradnji sa drugim tehnikama poveanja pouzdanosti.

    Dinamika softverska redundansa

    N-version programiranje je softverski ekvivalent statike, maskirajue redundanse, jer seotkaz komponente sakriva od spoljanjosti isvaka verzija ima statike relacije sa drugimverzijama i driverprocesom.

    Kod dinamike redundanse, redundantna komponenta se aktivira samo ukoliko doe dootkaza u osnovnoj komponenti. Ovaj pristup ima sledee faze:

    o Detekcija greke (engl. errror detection): veina otkaza e se na krajumanifestovati kao greke. Nijedan pristup oporavku od otkaza ne moe da seupotrebi ukoliko greka nije otkrivena.

    o Izolacija i procena tete (engl. damage confinement and assessment): kada sedetektuje greka, potrebno jeproceniti do koje mere je sistem ugroen i oteen.Kanjenje od trenutka nastanka otkaza do trenutka detekcije greke znai da se

    pogrena informacija moda proirila i na druge delove sistema.o Oporavak od greke (engl. error recovery): tehnike oporavka od greke treba da

    tee da transformiu sistem koji je oteen u stanje u kome e sistem nastavitinormalno operisanje (moda sa degradiranom funkcionalnou).

    o Tretman otkaza (engl. fault treatment): greka je samo simptom otkaza. Iako jeteta moda nadoknaena, otkaz moda jo uvek postoji i moe uzrokovati novugreku u daljem radu sistema, sve dok se sistem ne popravi.

    Detekcija greke

    Tehnike detekcije greke se mogu klasifikovati u sledee kategorije:o Detekcije u okruenju. U ovu kategoriju spadaju detekcije greaka u okruenju u

    kome se program izvrava. To mogu biti greke koje detektuje hardver, kao to sugreke tipa "illegal instruction executed" ili "arithmetic overflow" ili "memoryaccess violation". Tu spadaju i greke koje uoava izvrno okruenje (engl.runtime environment), kao to su greke tipa "value out of range" ili "array bounderror" ili "null pointer dereferencing".

    o Detekcije u aplikaciji. Ovde spadaju sledee tehnike provere greaka unutar sameaplikacije:

  • 7/31/2019 Skripta PRV

    40/299

    Programiranje u realnom vremenu 40

    Provere pomou replika (engl. replication checks): N-versionprogramiranje uoava greke poreenjem rezultataNnezavisnih replika.

    Vremenske provere (engl. timing checks): (a) watchdog timerje proces kojiaplikacija restartuje periodino, ukoliko ispravno radi; ukoliko doe dogreke, aplikacija "odluta" i ne restartuje ovaj proces, tako da njemu vreme

    istie i on generie signal o nastanku greke. (b) kontrola prekoraenjarokova (engl. deadline miss); ukoliko se rasporeivanje radi u okruenju,ovo se moe smatrati grekom detektovanom u okruenju.

    Reverzne provere (engl. reversal checks) su mogue u komponentama ukojima postoji jedan-na-jedan preslikavanje ulaza na izlaz; u tom sluaju seizlazni rezultat moe proveriti inverznom funkcijom i poreenjemdobijenog argumenta sa ulaznim. Npr. komponenta koja izraunava koren

    broja moe se proveriti prostim kvadriranjem izlaza (primetiti da jepotrebno neegzaktno poreenje zbog zaokruivanja).

    Provere pomou kodova (engl. coding checks) se koriste za kontrolugreaka u podacima, npr.parity, checksum, CRC i sl.

    Provere razumnosti (engl. reasonableness checks) se oslanjaju na znanje ointernoj konstrukciji sistema. One proveravaju stanje sistema i vrednosti

    izlaza u odnosu na to ta se sa njima treba raditi. Ove uslove provererazumnosti (engl. assertions) u programe ugrauju sami programeri. To sulogiki izrazi nad programskim varijablama koji treba da budu zadovoljeniu odreenim trenucima izvravanja programa.

    Strukturne provere (engl. structural checks) se odnose na provereintegriteta struktura podataka, npr. povezanosti listi. Oslanjaju se na

    tehnike kao to su brojanje referenci na objekte, redundantni pokazivai itd. Dinamike provere razumnosti (engl. dynamic reasonableness checks) se

    oslanjaju na pretpostavku da se npr. dva rezultata dobijena sa nekoganalognog ulaza u dva bliska vremenska trenutka ne mogu mnogo

    razlikovati zbog prirode ulaznog signala.

    Treba primetiti da se mnoge od ovih provera mogu vriti u hardveru i da se tada mogusmatrati grekama iz okruenja.

    Izolacija i procena tete

    Tehnikeprocene tete su tesno povezane sa tehnikama izolacije greke, jer se od trenutkanastanka otkaza do trenutka detekcije greke pogrena informacija moda proirila podrugim delovima sistema i okruenja.

    Izolacija tete se zasniva na strukturiranju sistema tako da se minimizuje teta nastala zbogotkazane komponente.

    Jedna tehnika izolacije je modularizacija uz enkapsulaciju, pri emu se sistem deli namodule koji interaguju samo kroz jasno definisane i kontrolisane interfejse, dok su njihove

    implementacije sakrivene i nedostupne spolja. To doprinosi da se greka nastala u jednommodulu tee proiri i na druge. Ovo jestatiki pristup izolaciji.

    Dinamiki pristup izolaciji podravaju atomine akcije (engl. atomic actions). Atominaakcija je izolovana (engl. isolated) u smislu da za vreme njenog izvravanja nemainterakcija sa ostatkom sistema. Ona je i nedeljiva (engl. indivisible), u smislu da se ona u

    celini izvrava, sa svim efektima njenog celokupnog izvravanja; ukoliko doe do otkaza

    u toku njenog izvravanja, efekti na sistem i okruenje ne postoje. One se koriste daprevedu sistem iz jednog u drugo konzistentno stanje.

  • 7/31/2019 Skripta PRV

    41/299

    Programiranje u realnom vremenu 41

    Oporavak od greke

    Proces oporavka od greke je verovatno najvaniji element tolerancije otkaza. On mora dasistem sa grekom dovede u stanje normalnog operisanja, mada moda uz degradiranufunkcionalnost.

    Postoje dva pristupa oporavku od greke: oporavak unapred (engl. forward errorrecovery, FER) i oporavak unazad(engl. backward error recovery, BER).

    FER tehnike pokuavaju da nastave izvravanje od stanja sa grekom, selektivnokorigujui stanje sistema. To ukljuuje aktivnosti koje treba da svaki aspekt kontrolisanogokruenja koji je oteen ili opasan uine sigurnim. Ove aktivnosti su sasvim specifine zadati sistem i zavise od preciznosti procene lokacije i uzroka greke. Na primer, korienjeredundantnih pokazivaa koji se koriste kao rezerva za oteene, ili samokorigujuihkodova.

    BER tehnike se zasnivaju na vraanju sistema u sigurno prethodno stanje pre nastankagreke i izvravanje alternativne sekcije programa.

    Taka restauracije sistema se naziva taka oporavka (engl. recovery point) i predstavljatrenutak u kome se stanje sistema (koje se smatra konzistentnim i sigurnim) pamti radikasnije eventualne restauracije. Kada doe do greke, stanje sistema se restaurira na

    poslednju proenu taku oporavka (engl. rollback). Prednost ovakve tehnike je to ne zavisi od uzroka i lokacije greke, ve se njen efekat

    jednostavno ponitava. Zato se ova tehnika moe koristiti i za oporavak od greaka koje sene mogu predvideti, kao to su greke u implementaciji.

    Meutim, BER tehnike imaju i znaajne nedostatke:o Ne moe se ponititi efekat promene okruenja (npr. jednom ispaljeni projektil ne

    moe se zaustaviti).o Implementacija pamenja stanja moe da bude veoma sloena i zahtevna po

    pitanju vremena u toku izvravanja.o Kod konkurentnih procesa koji meusobno komuniciraju mogu je tzv. dominoefekat (engl. domino effect): u primeru na slici, ukoliko greka u naznaenomtrenutku nastane u procesu P1, samo on se razmotava do take oporavka R13;meutim, ukoliko greka nastane u procesu P2, zbog potrebe ponitavanja efektameusobne razmene informacija i uticaja na drugi proces, nastaje domino efekat

    jer se oba procesa moraju razmotavati unazad do jako daleke take; u najgoremsluaju, svi procesi koji interaguju se moraju potpuno ponititi, to moe biti jakoskupo.

  • 7/31/2019 Skripta PRV

    42/299

    Programiranje u realnom vremenu 42

    P1

    R11

    R12

    R13

    R21

    R22

    P2

    Terror

    Inter ProcessCommunication

    Inter Process

    Communication

    Inter Process

    Communication

    Inter Process

    Communication

    Zbog svega to je reeno, obe tehnike FER i BER imaju svoje prednosti i nedostatke.

    Najee se one upotrebljavaju kombinovano. FER tehnike su krajnje zavisne odaplikacije i nee biti dalje razmatrane.

    Blokovi oporavka

    Blok oporavka (engl. recovery block) predstavlja jeziku podrku za BER. Blok oporavka je jeziki konstrukt koji je blokkao u standardnom programskom jeziku,

    osim to se njegov ulazak implicitno smatra takom oporavka (engl. recovery point), anjegov izlaz je test prihvatljivosti (engl. acceptance test).

    Test prihvatljivosti se koristi da bi se proverilo da li je sistem u prihvatljivom stanju posleizvravanja bloka, odnosno njegovogprimarnog modula.

    Ako test prihvatljivosti nije zadovoljen, program se restaurira do take oporavka i izvravase alternativni modul, itd. Ako nijedan alternativni modul ne dovede do prolaska testa,

    oporavak se preduzima na viem nivou (u eventualnom okruujuem bloku oporavka).Blokovi oporavka se mogu ugneivati.

    Establish

    recovery

    point

    Enter

    recovery

    blockAny

    alternatives

    left?

    No

    Fail recovery block

    Yes

    Execute

    next

    alternative

    Evaluate

    acceptance

    testPass

    Discard

    recovery

    point

    Exit

    recovery

    block

    Restore

    recovery

    point

    Fail

    Mogua sintaksa ovog konstrukta:

  • 7/31/2019 Skripta PRV

    43/299

    Programiranje u realnom vremenu 43

    ensure by

    else by

    else by

    ...else by

    else error;

    Nijedan komercijalni i raireni jezik ne podrava direktno ovaj konstrukt, ali se on moerealizovati postojeim konstruktima i mehanizmima (npr. izuzecima). Kljuni problem urealizacijije pamenje i restauriranje take oporavka.

    Na primer, reavanje diferencijalnih jednaina moe se obaviti tzv. eksplicitnim Kuttametodom, koji je brz ali neprecizan za odreene jednaine, ali i implicitnim Kuttametodom, koji je skuplji ali uspeno reava sloene jednaine. Sledei primer obezbeujeda se efikasniji metod upotrebljava sve dok daje zadovoljavajue rezultate, a da se u

    sloenim situacijama koristi sloeniji i pouzdaniji metod; osim toga, ovaj pristup moe ida tolerie potencijalne greke u implementaciji eksplicitne metode, ukoliko je testprihvatljivosti dovoljno fleksibilan:

    ensure RoundingErrorWithinAcceptableToleranceby

    ExplicitKuttaMethodelse by

    ImplicitKuttaMethodelse error;

    Test prihvatljivosti obezbeuje detekciju greke koja omoguuje iskorienje redundanseu softveru. Dizajn testa prihvatljivosti je kljuan za efikasnost ove tehnike. Potrebno je

    pronai balans izmeu ugraivanja razumljivih testova prihvatljivosti u program itrokova njegovog izvravanja, pri emu se uva pouzdanost.

    Treba primetiti da se ovde radi o testu prihvatljivosti, a ne korektnosti, to znai dakomponenta moe da radi zadovoljavajue i sa degradiranom funkcionalnou.

    Sve ranije navedene tehnike detekcije greaka mogu se koristiti za formiranje testovaprihvatljivosti. Treba obratiti panju da pogreno implementiran test prihvatljivosti moeda dovede do situacije u kojoj se greke provlae nezapaeno.

    Poreenje izmeu N-version programiranja i blokova oporavka

    N-version programiranje (NVP) se oslanja na statiku redundansu u kojoj N verzijasoftvera radi istovremeno. Blokovi oporavka (RB) se oslanjaju na dinamiku redundansuu kojoj se alternativni moduli aktiviraju samo ukoliko se test prihvatljivosti ne proe.

    Obe varijante ukljuuju posebne trokove razvoja, jer obe zahtevaju realizacijuNrazliitihkomponenata. NVP jo zahteva realizaciju driver procesa. RB zahteva realizaciju testaprihvatljivosti.

    Tokom izvravanja, NVP generalno zahteva Nputa veu koliinu resursa nego jednavarijanta. Iako RB zahtevaju samo jedan skup resursa, potrebni su dodatni resursi i vreme

    izvravanja za uspostavljanje i restauraciju taaka oporavka. Obe tehnike iskoriavaju raznovrsnost izrade da bi tolerisale nepredvidive greke.

    Meutim, nijedna od njih ne moe dase bori protiv greaka zbog neispravne specifikacije

    zahteva.

  • 7/31/2019 Skripta PRV

    44/299

    Programiranje u realnom vremenu 44

    NVP koristi glasanje za detekciju greke, dok RB koristi test prihvatljivosti. Tamo gde jeegzaktno ili neegzaktno glasanje mogue, glasanje je generalno jeftinije nego izvravanjetesta. Meutim, u sluaju kada ono nije mogue, testovi su bolje reenje.

    RB ne mogu ponititi efekat na okruenje, ali se mogu strukturirati tako da se promeneokruenja ne rade u okviru blokova oporavka. NVP nema taj problem jer se smatra da su

    verzije modula izolovane i promene sredine se vre samo po donoenju odluke.

  • 7/31/2019 Skripta PRV

    45/299

    Programiranje u realnom vremenu 45

    Izuzeci i njihova obrada

    Dinamika redundansa i izuzeci

    Izuzetak(engl. exception) se moe definisati kao pojava greke. Greka se generalno definie kao manifestacija devijacije ponaanja od specifikacije.

    Greka moe biti predvidiva (npr. vrednost izvan zadatog opsega) ili nepredvidiva (npr.greka u implementaciji softverske komponente). ta se smatra grekom je esto relativnopitanje.

    Ukazivanje pozivaocu neke operacije na izuzetak koji je u njoj nastao naziva sepodizanje(engl. raising) ili signaliziranje (engl. signalling) ili bacanje (engl. throwing) izuzetka. Odgovor pozivaoca na podignut izuzetak naziva se obrada (engl. handling) izuzetka.

    Obrada izuzetka je FER mehanizam, jer ne postoji implicitni povratak sistema u sigurnostanje. Umesto toga, kontrola se vraa pozivaocu koji treba da preduzme proceduru zaoporavak. Meutim, mehanizam obrade izuzetaka moe se iskoristiti za implementacijuBER mehanizama.

    Mehanizam obrade izuzetaka moe se koristiti za:o reavanje abnormalnih uslova koji se pojavljuju u okruenju;o tolerisanje greaka u dizajnu softvera;o optu detekciju i oporavak od greaka.

    Mehanizam obrade izuzetaka u nekom programskom jeziku treba da zadovolji sledeeopte uslove:

    o Kao i ostali mehanizmi jezika, i on treba da bude jednostavan za razumevanje iupotrebu.

    o Kod za obradu izuzetka ne sme da bude rogobatan tako da ugrozi razumevanjeosnovnog toka bez pojave greaka.

    o Mehanizam treba da bude implementiran tako da ne uzima posebne resurse ivreme u toku izvravanja programa ukoliko izuzetaka nema, ve samo u sluajunjihove pojave.

    o Mehanizam treba da podjednako tretira izuzetke nastale u okruenju (npr. odstrane hardvera) i u samom programu (npr. zbog ne zadovoljavanja uslova

    korektnosti).

    Obrada izuzetaka bez posebne jezike podrke

    Ukoliko sam jezik ne podrava obradu izuzetaka, onda se neregularne situacije mogureavati pomou posebnih povratnih vrednosti iz potprograma, kao to je to uobiajeno uproceduralnim jezicima:

    if (functionCall(someParams)==OK) {// Normal operation

    } else {

    // Error handling code}

  • 7/31/2019 Skripta PRV

    46/299

    Programiranje u realnom vremenu 46

    Iako je ovaj mehanizam jednostavan, on ne zadovoljava ostale zahteve: kod je nejasan, jerne razdvaja jasno neregularnu od regularne staze, ukljuuje reijske trokove u svakomsluaju i nije jasno kako se obrauju izuzeci iz okruenja.

    U nastavku e se tretirati moderni koncepti i mehanizmi obrade izuzetaka u programskimjezicima, i to najvie u objektno orijentisanim jezicima C++ i Java.

    Izuzeci i njihova reprezentacija

    Kao to je ranije naglaeno, postoje dva izvora izuzetaka: okruenje programa (hardver iliizvrno okruenje) i sam program (aplikacija).

    Izuzetak se moe podii sinhrono, kao neposredni rezultat dela koda koji je pokuao nekuneregularnu operaciju, ili asinhrono, to znai nezavisno od operacije koja se trenutnoizvrava.

    Prema tome, postoje etiri kategorije izuzetaka:o

    Detektovani od strane okruenja i podignuti sinhrono. Na primer, izuzeci tipadeljenja sa nulom ili prekoraenje granica niza.Za C++, generisanje ovakvih izuzetaka nije garantovano, ve zavisi odimplementacije. Izvrno okruenje ne generie ovakve izuzetke (nema nikakve

    provere u vreme izvravanja), pa je sama aplikacija odgovorna za detekcijuovakvih greaka.Java dosledno generie sve tipove ovakvih izuzetaka.

    Na primer, sledei kod na jeziku C++ moe (ali ne mora) da podigne hardverskiizuzetak koji nije uhvaen od strane programa, dok se u jeziku Java podieodreeni izuzetak:

    int a[N];

    ...for (int i = 0; i

  • 7/31/2019 Skripta PRV

    47/299

    Programiranje u realnom vremenu 47

    Asinhroni izuzeci se obino nazivaju asinhronim signalima (engl. asynchronous signal) ipojavljuju se u kontekstu konkurentnog programiranja.

    Za sinhrone izuzetke, bitan element mehanizma je kako se oni deklariu. Postoje dvanajea pristupa:

    o Izuzetak je eksplicitno deklarisana konstanta (jezik Ada).o Izuzetak je objekat nekog tipa (C++ i Java).

    U jeziku C++, izuzetak moe biti instanca bilo kog tipa, i ugraenog i korisnikog(objekat klase). U trenutku podizanja izuzetka, kreira se jedan privremeni, bezimeni

    objekat (smeta se u statiki alociranu memoriju) i inicijalizuje izrazom iza naredbethrow. U trenutku pokretanja bloka koji obrauje izuzetak (engl. handler) iza naredbecatch, formira se argument tog bloka kao automatski lokalni objekat tog bloka koji se

    inicijalizuje navedenim privremenim objektom. Semantika inicijalizacije u oba sluaja jeista kao i kod prenosa argumenata u funkciju. Na primer, izuzetak se moe podii ovako:

    if (...) throw HighTemperatureException(...);

    ili ovako:

    HighTemperatureException* preparedException = new HighTemperatureException;...if (...) throw preparedException;

    ili ovako:

    if (...) throw new HighTemperatureException(...);

    a onda uhvatiti ovako:

    catch(HighTemperatureException e) {...

    }

    odnosno ovako:

    catch(HighTemperatureException* e) {...delete e;

    }

    U jeziku Java, izuzetak je instanca klase direktno ili indirektno izvedene iz klaseThrowable. Njegov ivotni vek je isti kao i ivotni vek bilo kog drugog objekta klase(nastaje eksplicitno i unitava se implicitno). Od izvora izuzetka do onoga ko ga hvata

    prosleuje se, zapravo, samo referenca na taj objekat. Na primer, izuzetak se moe podiiovako:

    HighTemperatureException preparedException = new HighTemperatureException;

    ...if (...) throw preparedException;

    Ili ovako:

    if (...) throw new HighTemperatureException(...);

    a uhvatiti ovako:

    catch(HighTemperatureException e) {...

    }

    U jeziku C++ deklaracija funkcije moe da ukljuuje i spisak tipova izuzetaka koje tafunkcija moe da podigne, bilo direktno (iz svog koda), bilo indirektno (iz ugneenih

    poziva drugih funkcija, tranzitivno). Ukoliko ovaj spisak postoji, funkcija ne moe podiiizuzetak nijednog drugog tipa osim onih sa spiska, ni direktno ni indirektno. Ukoliko taj

  • 7/31/2019 Skripta PRV

    48/299

    Programiranje u realnom vremenu 48

    spisak ne postoji, funkcija moe podii izuzetak bilo kog tipa (zbog kompatibilnosti sajezikom C i starijim verzijama jezika C++). Na primer:

    void checkTemperature () throw (HighTemperatureException*);

    U jeziku Java postoji slian princip, osim to ukoliko funkcija ne sadri spisak izuzetaka,onda ona ne moe podii nijedan. Ovaj pristup je znaajno restriktivniji, ali time ipouzdaniji. Na primer:

    public void checkTemperature () throws HighTemperatureException {...}

    U jeziku C++ ne postoji predefinisana hijerarhija klasa ili tipova za izuzetke, ve onimogu biti bilo kog tipa.

    U jeziku Java, hijerarhija izuzetaka poinje klasom Throwable i izgleda kao na datoj slici.Throwable

    User-defined exceptions

    Error Exception

    LinkageErrorVirtualMachine

    Error

    RunTimeExcep

    tion

    unchecked

    exception

    checked

    exception

    Key:

    U jeziku Java, izuzeci koji se ne proveravaju (engl. unchecked) ne moraju da se navode ulisti izuzetaka koje funkcija podie, oni se uvek podrazumevaju. Ove izuzetke podieokruenje (npr. linker ili virtuelna maina, ili su to greke u izvravanju, npr. neregularnakonverzija reference ili prekoraenje granica niza). Ostali tipovi izuzetaka se morajudeklarisati u deklaraciji funkcije ukoliko ih ona direktno ili indirektno podie (engl.unchecked). Korisniki definisani tipovi izuzetaka realizuju se kao klase izvedene iz klaseException.

    Obrada izuzetka

    U nekim programskim jezicima kod za obradu izuzetka (engl. exception handler) moe sepridruiti pojedinanoj naredbi. Meutim, u veini blok-strukturiranih jezika, kod zaobradu izuzetaka je vezan za blok.

    U jezicima C++ i Java, blok koji moe da izazove izuzetak koji treba uhvatiti deklarie sekao try blok:

    try {

    // Neki kod koji moe podii izuzetak

    } catch (ExceptionType e) {

    // Exception Handler za izuzetke tipa ExceptionType

    }

  • 7/31/2019 Skripta PRV

    49/299

    Programiranje u realnom vremenu 49

    Prilikom izvravanja, najpre se izvrava blok iza try. Ukoliko se tokom njegovogizvravanja ne podigne izuzetak (ni u ugneenim pozivima), ceo konstrukt se zavrava.Ukoliko doe do izuzetka koji je tipa navedenog u argumentu catch naredbe (uz praviloobjektne supstitucije, tj. prihvataju se i izvedeni tipovi), izvrava se kod za obradu u blokuiza catch. Ukoliko tip iza catch ne prihvata tip podignutog izuzetka, ovaj izuzetak se

    prosleuje u okruujui kontekst poziva (prvi dinamiki okruujui try blok unutar istefunkcije ili pozivaoca).

    Oblast obrade izuzetka i njena granularnost zapravo odreuju preciznost odreivanjalokacije izvora greke. Ukoliko je potrebna finija granularnost, u sam objekat izuzetkamogu se ugraditi dodatne informacije kao parametri izuzetka, ili sam tip izuzetka moenosi dodatnu informaciju.

    Na primer, potrebno je oitati tri senzora za temperaturu, pritisak i protok, pri emu kodsvakog itanja moe nastupiti izuzetak zbog prekoraenja opsega dozvoljenih vrednosti;zatim treba preduzeti odgovarajue akcije. Naivan pristup bi bio sledei:

    try {

    // Read temperature sensor} catch (Overflow ovf) {// Handler for temperature overflow

    }try {

    // Read pressure sensor} catch (Overflow ovf) {

    // Handler for pressure overflow}try {

    // Read flow sensor} catch (Overflow ovf) {

    // Handler for flow overflow}

    // Now adjust the temperature, pressure, and flow// according to the requirements

    Meutim, ovakav pristup je nepregledan i zamoran. Loe je to je kod za obradu i zuzetkanepregledno ueljan u sam osnovni regularni tok. Bolji pristup je da se informacija o vrstiizuzetka ugradi u njegov tip ili u njegove atribute. Na primer:

    try {// Read temperature sensor// Read pressure sensor// Read flow sensor

    }catch (TemperatureOverflow ovf) {

    // Handler for temperature overflow

    }catch (PressureOverflow ovf) {// Handler for pressure overflow

    }catch (FlowOverflow ovf) {

    // Handler for flow overflow}// Now adjust the temperature, pressure, and flow// according to the requirements

    Propagacija izuzetka

    Pitanje je kako tretirati situaciju kada bloku u kome moe nastati izuzetak nije pridruenblok za njegovu obradu. U jezicima postoji nekoliko pristupa:

  • 7/31/2019 Skripta PRV

    50/299

    Programiranje u realnom vremenu 50

    o Tretirati to kao greku u programu koja se moe otkriti u vreme prevoenja. Ovo jedosta restriktivan pristup, jer vrlo esto nije mogue obraditi izuzetak tamo gdenastaje; na primer, kod izuzetaka koji nastaju zbog neregularnih argumenata

    procedure.

    o Propagirati izuzetak u vreme izvravanja u okruujuu proceduru (pozivaoca), tj.redom navie, sve dok se ne nae pozivalac koji ima kod za obradu izuzetka.

    Osnovno pitanje kod obrade izuzetaka je da li podiza izuzetka treba da nastavi svojeizvravanje posle obrade izuzetka ili ne. Postoje dva generalna pristupa: model povratka(engl. resumptionmodel) i model terminacije (engl. termination model).

    Kod resumption modela, podiza izuzetka nastavlja svoje izvravanje posle obradeizuzetka, od mesta na kome je nastao izuzetak.

    Na primer, neka postoje tri procedure, P, Q iR koje se redom pozivaju kao na donjoj slici.Neka Rpodie izuzetakrza koji nema kod za obradu. Takav kod za obradu se trai u

    pozivajuoj proceduri Q koja ima kod za obraduHr. Pokree se izvravanje tog koda, alineka i on podie izuzetak q za koji se kod za obradu pronalazi u proceduri P. Posle

    zavretka ove obrade, izvravanje se vraa na mesto nastanka izuzetka u Hr koji sezavrava, a zatim se nastavlja izvravanje procedure R od mesta na kome je nastaoizuzetak.

    P

    Hq

    Q

    Hr

    R

    1: P invokes Q

    2: Q invokes R3: R raises exception r

    4: Hr raises exception q 5: Hq resumes Hr

    6: Hr resumes R

    Ovaj mehanizam se moe najlake razumeti ako se kod za obradu izuzetka posmatra kao

    procedura koja se implicitno poziva pri nastanku izuzetka i koja se dinamiki trai upozivajuim procedurama.

    Problem sa ovim pristupom je to je esto nemogue popraviti otkaze u okruenju tako dase nastavi izvravanje. Problem je restaurirati kontekst izvora izuzetka posle zavretkaobrade izuzetka. Zbog toga je implementacija strogog resumption modela veoma sloena.Kompromis postoji u vidu retrymodela, kod koga se ceo blok izvrava ispoetka.

  • 7/31/2019 Skripta PRV

    51/299

    Programiranje u realnom vremenu 51

    Terminationmodel podrazumeva da se kontrola ne vraa na mesto nastanka izuzetka poslenjegove obrade, nego se blok ili procedura koja sadri kod za obradu zavrava a kontrolavraa pozivaocu. Kada je kod za obradu unutar bloka, kontrola se posle obrade nastavljaod prve naredbe iza tog bloka. Primer je pokazan na donjoj slici:

    P

    Q

    12: P invokes Q

    Hr

    3

    R

    4: P invokes Q

    5

    6: R raises exception r

    7

    9: Procedure terminates

    Jezici C++ i Java podravaju terminationmodel na potpuno isti nain. Jedina specifinost

    jezika C++ je da se pri prenosu kontrole na kod za obradu pozivaoca "razmotava stek", tj.

    propisno unitavaju (pozivom destruktora) svi automatski objekti klasa kreirani odtrenutka ulaska u blok iji je kod za obradu pronaen, do trenutka nastanka izuzetka. U

    jeziku Java za ovo nema potrebe, jer ne postoje automatski objekti klasa.

    Mogu je i hibridni model, kod koga kod za obradu izuzetka moe da odlui da li jegreka popravljiva ili ne i da li e se izvravanje nastaviti na mestu nastanka izuzetka iline.

    Zadaci

    2.1. N-Version programiranje

    Korienjem N-version programiranja realizovati pouzdan program koji sortira niz celihbrojeva.

    Reenje:

    1. (sekvencijalno reenje)

    const int N = .. // dimenzija niza

    void quickSort(int*, int);void insertSort(int*, int);void bubbleSort(int*, int);

    void main() {

    int a[N] = {..}; // niz koji se sortiraint a1[N], a2[N], a3[N]; // pomocni nizovi

  • 7/31/2019 Skripta PRV

    52/299

    Programiranje u realnom vremenu 52

    int n = N;copy(a1, a, n);copy(a2, a, n);copy(a3, a, n);

    quickSort(a1, n);insertSort(a2, n);

    bubbleSort(a3, n);

    vote(a1, a2, a3, n); // drajver: npr. sekvencijalno poredjenje}

    2. (niti)

    class SortThread:Thread {public:

    SortThread(void(*body)(),int* a1, int n1) myBody(body){ a=a1;n=n1;}

    ReentrantBarrier* Instance();protected:

    virtual void run();private:int* a;int n;...

    };

    Instance() {static ReentrantBarrier b;return &b;

    }

    run() {

    (*body)(a,n);Instance()->join();}

    /*glavni program*/void main() {

    //inicijalizacijaSortThread* qS = new SortThread(quickSort);SortThread* iS = new SortThread(insertionSort);SortThread* bS = new SortThread(bubbleSort);

    qS.start();iS.start();

    bS.start();SortThread::Instance()->join();

    vote(a1, a2, a3, n);}

    2.2. Blokovi oporavka

    Korienjem mehanizma obrade izuzetaka, pokazati kako se blokovi oporavka moguimplementirati u jeziku C++.

    ensure

    byelse by

  • 7/31/2019 Skripta PRV

    53/299

    Programiranje u realnom vremenu 53

    else by

    ...else by

    else error;

    Reenje:

    (I)

    Prvo reenje koristi statiki ugneene blokove. Kada prvi blok otkae, hvata se izuzetak tipaEResultBadi primenjuje se sledei blok. Ako je operacija koju blok izvrava obavljenauspeno hvata se izuzetak tipa EResultOKi izvravanje programa se nastavlja.

    // SortAlgorithms.h

    typedef int EAcceptTestPassed;typedef int EAcceptTestFailed;

    class SortAlgorithms{public:

    static void bubbleSort(int iArray[], int iLength);static void insertionSort(int iArray[], int iLength);static void quickSort(int iArray[], int iLength);

    };

    void acceptanceTest(int originalArray[], int iLength, int sum) throw(EAcceptTestPassed, EAcceptTestFailed);

    /* copyArray* Kopira sadrzaj niza array1 u niz array2*/void copyArray(int array1[], int array2[], int length){

    for (int i=0; i

  • 7/31/2019 Skripta PRV

    54/299

    Programiranje u realnom vremenu 54

    int checkSum=0;

    for (int i=0; i

  • 7/31/2019 Skripta PRV

    55/299

    Programiranje u realnom vremenu 55

    int sum1=0;

    for (int i=0; i= originalArray[i+1])

    throw EAcceptTestFailed;else

    sum1 += originalArray [i];}if (sum1 == sum) throw EAcceptTestPassed;

    else throw EAcceptTestFailed;

    }

    (II)

    Drugo reenje koristi projektni uzorakStrategy prikazano na klasnom dijagramu. Objektiklasa izvedenih iz SortStrategyse smetaju u red pa se redom primenjuju dok se ne

    zadovolji test prihvatljivosti.

    // SortStrategy.h

    #ifndef _SortStrategy_h_#define _SortStrategy_h_

    typedef int EAcceptTestPassed;typedef int EAcceptTestFailed;

    void acceptanceTest() throw (EAcceptTestPassed, EAcceptTestFailed);

    abstract class SortStrategy{protected:

    int *iArray;int iArrayLength;

    virtual void sort(int *iArray, int iLength);

  • 7/31/2019 Skripta PRV

    56/299

    Programiranje u realnom vremenu 56

    public:SortStrategy();

    };

    class InsertionSortStrategy : public SortStrategy{protected:

    void sort(int *iArray, int iLength);public:

    InsertionSortStrategy();};

    class BubbleSortStrategy : public SortStrategy{protected:

    void sort(int *iArray, int iLength);public:

    BubbleSortStrategy();};

    class QuickSortStrategy : public SortStrategy

    {protected:

    void sort(int *iArray, int iLength);public:

    QuickSortStrategy();};

    #endif

    // DynamicRedundancy02.cpp

    /* Inicijalizacija kao u prvom reenju */

    /* Kreiranje sort strategija i njihovo stavljanje u red */

    Queue ssQueue;QuickSortStrategy qSort;InsertionSortStrategy insSort;BubbleSortStrategy bbSort;

    ssQueue.put(&qSort);ssQueue.put(&insSort);ssQueue.put(&bbSort);

    /* kreiranje checkpoint-a */copyArray(iArray, iWorkingArray, iArrayLength);

    /* Izvodjenje kriticne operacije - sortiranja */try

    {while(!ssQueue.empty()){

    try{

    SortStrategy* ss = ssQueue.get();ss->sort(iWorkingArray, iArrayLength);acceptanceTest(iWorkingArray, iArrayLength, checkSum);

    }catch(EAcceptTestFailed failed){

    /* restaurira se checkpoint */copyArray(iArray, iWorkingArray, iArrayLength);

    }

    }}catch(EAcceptTestPassed passed)

  • 7/31/2019 Skripta PRV

    57/299

    Programiranje u realnom vremenu 57

    {copyArray(iWorkingArray, iArray, iArrayLength);

    }

    /* Ispis rezultata */cout

  • 7/31/2019 Skripta PRV

    58/299

    Programiranje u realnom vremenu 58

    2.4. Test prihvatljivosti

    Dato je zaglavlje klase Listkoja je implementira jednostruko ulananu listu i zaglavlje klaseListIterator koja slui za sekvencijalni obilazak elemenata date liste. Implementirati testprihvatljivosti

    int check(List* l)

    koji vri proveru da li u datoj listi postoji petlja.

    class Object;class List {public:

    List ();~List ();//...ListIterator* createIterator(); //vraa iterator za datu listu

    };class ListIterator {

    public:void reset();int next ();int isDone();

    Object* currentItem();};

    Reenje:int check(List* l){

    int i = 0;

    ListIterator* i1 = l->createIterator(),*i2 = l->createIterator();

    do{

    i1->next();

    if(i1->currentItem() == i2->currentItem())return 0;

    if((++i)%2)i2->next();

    }while(!i1->isDone());

    return 1;}

    Zadaci za samostalan rad

    2.5.

    Dat je interfejs klase koja omoguava itanje znakova sa terminala, a poseduje i operaciju zaodbacivanje svih preostalih znakova na tekuoj liniji. Operacije ove klase podiu izuzetak tipaIOError.

    class CharacterIO {public:

  • 7/31/2019 Skripta PRV

    59/299

    Programiranje u realnom vremenu 59

    char get () throw (IOError);void flush () throw (IOError);

    };

    Klasa Looksadri funkciju read()koja pretrauje tekuu ulaznu liniju i trai sledee znakoveinterpunkcije: zarez, taku i taku-zarez. Ova funkcija e vratiti prvi sledei znak

    interpunkcije na koji naie ili podii izuzetak tipa IllegalPunctuation ukoliko naie naznak koji nije alfa-numeriki. Ako se tokom uitavanja znakova sa ulazne linije dogodiizuzetak tipa IOError, on e biti prosleen pozivaocu funkcije read(). Kada vrati regularanznak interpunkcije, ova funkcija treba da odbaci preostale znakove na liniji.

    Realizovati klasu Look korienjem klase CharacterIO. U klasi Look zatim realizovati ifunkciju getPunctuation() koja e uvek vratiti sledei znak interpunkcije, bez obzira na

    postojanje neregularnih znakova i greaka na ulazu. Pretpostaviti da je ulazni tok neogranien,da uvek sadri neki znak interpunkcije i da se greke na ulazu deavaju sluajno.

    2.6.

    Posmatra se neki sistem za kontrolu procesa u kome se gas zagreva u nekoj posudi. Posuda jeokruena hladnjakom koji smanjuje njegovu temperaturu odvoenjem toplote preko tenostiza hlaenje. Postoji takoe i slavina ijim se otvaranjem gas isputa u atmosferu. Interfejsklase koja upravlja ovim procesom dat je u nastavku. Zbog sigurnosnih razloga, klasa

    prepoznaje nekoliko neregularnih uslova koji se korisniku dojavljuju putem izuzetaka.

    Izuzetak tipa HeaterStuckOn signalizira da greja nije mogue iskljuiti jer se prekidazaglavio. Izuzetak tipa TemperatureStillRising signalizira da hladnjak nije u stanju da

    snizi temperaturu gasa poveanjem protoka tenosti za hlaenje. Konano, izuzetak tipaValveStucksignalizira da se slavina zaglavila i da je nije mogue otvoriti. Operacija panic()

    podie znak za uzbunu.

    class TemperatureControl {public:void heaterOn ();void heaterOff () throw (HeaterStuckOn);void increaseCoolant () throw (TemperatureStillRising);void openValve () thr