Date post: | 05-Apr-2018 |
Category: |
Documents |
Upload: | marko-radic |
View: | 269 times |
Download: | 0 times |
of 299
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