Schrijfsels Document : realtime.txt

File index
Realtime omgevingen 2006-05-14
Door Pascal Schiks (C) Feb 2004 GNU/GPL
2009-05-13:Update

Introductie
Regelmatig worden mij vragen gesteld met betrekking tot realtime toepassingen.
Over dit onderwerp is eigenlijk niet zo heel erg veel duidelijke Nederlandstalige literatuur te vinden,
dus probeer ik in dit verhaal een en ander uit de doeken te doen.

Realtime wat is dat eigenlijk ?
Realtime per definitie
Er zijn verschillende interpretatie's over wat realtime nu eigenlijk is.
De meeste gaan er van uit dat de applicatie met een gangbaar besturingssysteem
moet kunnen werken, of vereisen in het geheel geen daadwerkelijke realtime performance.
Om een applicatie daadwerkelijk in realtime uit te kunnen voeren,
moet echter aan de volgende kriteria worden voldaan.
- Gegarandeerde tijdsinterval waarop de applicatie processortijd krijgt.
- Een gegarandeerde minimale hoeveelheid rekentijd.
- Er mogen in bovenstaande geen onderbrekingen (Interrupts) plaatsvinden

Eenvoudiger gezegt,
De applicatie moet een vast aantal malen per seconde rekentijd krijgen,
en deze rekentijd moet een minimale tijdsduur hebben.

Een praktisch voorbeeld:
Hebben we bijvoorbeeld een programma dat TV frames genereerd met een frequentie
van 25 Hz, dan moet dit programma 25 maal per seconde aangeroepen worden.
Het programma moet een heel frame kunnen berekenen.
Waneer dit minimaal 1ms en maximaal 4ms duurt dan moet er een gegarandeerde
rekentijd van 4ms beschikbaar zijn.
Het zal duidelijk zijn dat die 4ms in dit geval wat aan de krappe kant is
een minimum rekentijd van 4.5ms lijkt dan wat rieeler
Verder mag er tijdens de berekeningen geen onderbreking b.v. voor het afhandelenvan Disk I/O plaatsvinden,
Want anders is de beschikbare rekentijd niet gegarandeerd en kan het berekenen
van het frame te laat afgerond zijn.
Deze beperking geld overigens ook voor de hardware interrupts die noodzakelijk
zijn om onze applicatie I/O operaties naar bijvoorbeeld een grafische kaart
te laten uitvoeren.

Ook mogen hardware interrupts de tijds intervallen niet beinvloeden.
En natuurlijk mag het geheugen van de RealTime applicatie uiteraard niet
geswapped worden.
Dit is immers een duidelijke Disk I/O operatie waarvan de tijdsduur onbekend is.

Het moge duidelijk zijn dat reguliere besturings systemen in het algemeen
niet aan bovengestelde eisen kunnen voldoen.
Voor het berekenen van ons TV frame is een afwijking nog niet zo erg,
maar voor de besturing van zeer nauwkeurige machienes, kan een kleine afwijking
al fataal zijn.

Realtime applicaties
Ook aan de RealTime applicatie zelf worden speciale eisen gesteld.
- Het programma moet bij elke aanroep voledig (van boven tot onder)
doorlopen worden, waarbij er wel delen mogen worden overgeslaan.
- Het programma moet bij de eerste aanroep de noodzakelijke variabelen
een begin waarde geven (initialiseren).
- Het mag de beschikbare rekentijd niet overschrijden.
Een eenvoudige controle hierop valt aan te raden !
- Er mogen geen I/O operaties uitgevoerd worden, tenzij deze een gegarandeerde
tijd innemen.
Interupt based I/O handelingen zoals Disk toegang zijn dus uit den boze.
- Er mag runtime bij voorkeur geen geheugen gereserveerd worden.

Het programma wordt voor elke itteratie door de realtimetaskscheduler
op vaste tijdstippen aangeroepen.
we praten nu over een synchrone taak.

Een eenvoudig realtime c programma dat aan de gestelde eisen voldoet,
is het volgende voorbeeld dat realtime de afgelegde weg berekend
aan de hand van een gegeven snelheid en tijd.

int realtime_afgelegdeweg(float dT)
{
static int eerste_keer=1; /* initialisatie vlag */
extern int overrun; /* tijd overrun controlle */
extern float S; /* Afgelegde weg */
extern float v; /* snelheid */

overrun=1;

/* Initialiseer aleen de eerste maal */
if(eerste_keer)
{
eerste_keer=0; /* zorg dat deze code slechts 1 * uitgevoerd word */
V=10.0; /* Zet de snelheid op de begin waarde */
S=0.0; /* Zet de afgelegde weg op de begin waarde */
}

/* Realtime berekening */
S=S+V*dT; /* afgelegde weg = afgelegde weg + snelheid*Tijd */

/* bericht dat de rekentijd niet is overschreden */
overrun=0;
}

Dit programma voldoet aan alle bovengenoemde eisen
Het probleem van de I/O is opgelost door de variabelen S en V door
een ander programma (al dan niet realtime) te laten verwerken.
de parameter dT komt vanuit de realtimetaskscheduler en heeft een vaste waarde.

Note dat in sommige gevallen tijdens de initialisatie een overrun kan worden
toegestaan.
dit kan in ons geval gerealiseerd worden door de variabele eerste_keer ook
extern te declareren en de realtimetaskscheduler naar zowel
eerste_keer als overrun te laten kijken.

Iteratie tijd
In realtime processen wordt als regel vaak geintegreerd, zoals in he
bovenstaande voorbeeld waar gold dat :

S = S + v * dT

De afstand S die er berekent wordt is :
de al afgelegde afstand S + de snelheid v maal de verlopen tijd dT

dT wordt bepaald door het aantal malen per seconde dat de realtime taak wordt
aangeroepen.
Dit noemen we de iteratietijd.
de iteratietijd is 1 / iteratie frequentie.

Subanding
Waneer wij een zeer fors realtime programma hebben,
kan het voorkomen dat de beschikbare rekenkracht niet voldoende is
om het programma voledig ten uitvoer te brengen.
In zo'n geval ligt de oplossing in het verdelen van de load.
n.l. niet alle programma delen hoeven per se met een gelijke frequentie
afgehandeld te worden.
Berekenen we bijvoorbeeld in ons programma naast de afgelegde weg
ook het motorvermogen versus de stand van de bedieningshendel van het voertuig,
dan mag je er in ons geval van uitgaan dat deze per itteratie maar weinig
zal veranderen en de snelheid ook maar weinig zal beinvloeden.
deze berekening mag dus best minder vaak uitgevoerd worden
Hetzelfde kan gelden voor de brandstof voorraad van het voertuig.
we kunnen nu de belasting van de computer mooi verminderen
door de functies als volgt te verdelen.

S=S+V*dt; /* deze bereking word met voledige frequentie uitgevoerd */
if(subband)
{
vermogen=gashandlepositie();
}
else
{
brandstof=brandstof-(verbruik*2.0*dT);
}
subband=(subband==0); /* bij elke itteratie veranderd deze tussen 0 en 1 */

Deze techniek wordt subbanding genoemd.
We moeten er nu wel rekening mee houden dat dT door het subbanden gehalveerd is
en dus welicht * 2 gedaan moet worden !
Het is uiteraard ook mogelijk om de realtimetaskscheduler een deel van dit
subbanden voor zijn rekening te laten nemen.
In dat geval worden er gewoon meerdere taken gestart die met elkaar
kunnen communiceren.

Communicatie naar de buitenwereld
Zoals al eerder aangegeven, is het niet toegestaan om tijdens de uitvoer
realtime programma's acties te ondernemen welke de realtime performance
nadelig kunnen beinvloeden.
Dit kan bijvoorbeeld het geval zijn bij I/O operaties waarbij interrups
worden gebruikt.
Een oplossing voor dit probleem kan gezocht worden in het gebruik van
DMA technieken, waarbij grotere hoeveelheden data met randapparatuur wordt
uitgewisseld.
Echter voor veel zaken die op de computer zelf moeten plaatsvinden
kan de oplossing gezocht worden in een programmadeel dat niet realtime
uitgevoerd wordt.
Een voorbeeld hiervan in het volgende programmadeel

extern float V;
extern float S;

fprintf(TTY,"Snelheid %f Afgelegde weg %f\n",V,S);

Het schrijven naar de TTY poort mag best even onderbroken worden,
dit zal de berekeningen niet beinvloeden.
We hebben het hierbij over een asynchrone taak.

Dit zelfde geld voor het runtime inlezen of wegschrijven van bestanden.
Heb je b.v. in je realtime taak een database nodig.
Dan zul je deze door een asynchrone taak moeten laten inlezen om de data
vervolgens door te geven naar de realtime taak.
dit kan plaatvinden dmv een globale array (niet erg fraai maar wel veel voorkomend),
dmv van een pointer naar een structure
of b.v. dmv pipes (RT-Linux)

De realtime Task Scheduler
De bovenstaande programmadelen worden aangeroepen door de realtimetaskscheduler
Deze zorgt ervoor dat realtime delen op tijd worden uitgevoerd,
dat er tijdens het uitvoeren hiervan geen onderbrekingen plaatsvinden
(disable interrupts) en controleert of het programma niet vasthangt of
gewoon te veel rekentijd inneemt.
De overige rekentijd word verdeeld onder de asynchrone taken.
een van die asynchrone taken kan een besturings systeem zijn.

Latency
Omdat er dus veelal met meerdere programmadelen wordt gewerkt,
kan het voorkomen dat de resultaten van een actie of een wijziging
meer dan een iteratie achterlopen op de veroorzaker ervan.
Stel we hebben een analoge waarde die een gashandle representeert
en we lezen deze met subbanding uit (de waarde zal immers niet zo heel snel
veranderen)
en in een andere band krijgen we als eindresultaat een analoge waarde
die uiteindelijk aan een motor is verbonden,
dan kan het een aantal iteraties duren voordat een wijziging van de gashandle
uiteindelijk bij de motor aankomt.
Dit tijdsverloop noemen we latency.
Het is zaak om het schedulen het gehele systeem zodanig uit te voeren,
dat de latency binnen een acceptabele waarde wordt gehouden.
Bij zeer complexe systemen waarbij meerder realtime systemen moeten
samenwerken en er ook nog vaak sprake is van vertraging als gevolg van
communicatie kanalen, valt dit allemaal nog niet mee.
Latency problemen zijn dan ook lastig op te lossen.

Realtime in de praktijk
Het moge inmiddels wel duidelijk zijn dat de uitvoering van RealTime taken
geen sinnecure is.
De meeste besturingssystemen zijn niet in staat om aan de gestelde eisen te
voldoen.
De reden hiervoor ligt hem hem meestal in het feit dat de taskscheduler
(we spreken hier dus wel over multitasking) een systeem toepast waarbij
de rekentijd ongeveer gelijkwaardig over de lopende processen verdeeld wordt.
Daarnaast houd de scheduler geen rekening met het feit dat kernelprocessen
ook rekenkracht vereisen.
Om dit probleem te overkomen zijn er in het algemeen de volgende oplossingen mogelijk.

- Gebruik geen multitasking systeem
Gebruik bijvoorbeeld het oude MSDOS, hiermee is uitstekend een realtime-
omgeving te realiseren.
Een wat rieeler voorstel is het gebruik van VX-Works.
Dit is UNIX look and feel single task besturings systeem en wordt
veel voor embedded realtime toepassingen gebruikt.

- Gebruik een besturings systeem met een MicroKernel
Dit is verreweg de beste oplossing.
Het enige dat moet gebeuren is ervoor zorgen dat de taskscheduler word
vervangen door een versie die meer rekening houd met de RT eisen.
Systemen die hiervoor o.a. in aanmerking komen zijn :
QNX, OS-X, Solaris, RT11, HP-UX en AIX.

- Laat het OS als asynchrone taak draaien.
Dit is de meest gebruikte oplossing, dit omdat de meeste UNIX systemen
nu eenmaal een monolytisch kernel hebben.
De taskscheduler van het besturings systeem wordt hierbij
door de RealTimeTaskScheduler als asynchrone taak uitgevoerd.
Een belangrijk nadeel hiervan is dat bij een realtime programma fout
het hele systeem kan vastlopen.
Veel toegepaste systemen voor deze oplossing zijn :
MicroSoft Windows en tot op zekere hoogte Linux

Andere RealTime oplossingen
In sommige situaties zijn de genoemde problemen niet te overkomen.
Een techniek die minder accuraat en betrouwbaar is maar toch wel veel wordt
toegepast kan als volgt worden geilustreerd.

do
{
current_time=gettime();
dT=old_time - current_time;

S=S+V*dt;

old_time=current_time;
}
while(!shutdown);

Het programma heeft een onregelmatige itteratie frequentie,
en compenseerd dit door de itteratie tijd steeds aan te passen.
de berekening loopt welliswaar steeds een itteratie achter op te tijd
maar het systeem werkt in veel gevallen goed genoeg om acceptabele resultaten
te behalen.
Erg nauwkeurig is het echter niet, en dat valt over een lange periode
zeker te merken.

Een andere manier of realtime gedrag te verkrijgen, is de verwerking laten begrensen door de verwerkingssnelheid van de hardware.
Een voorbeel daarvan kan de geluidskaart zijn.
Waneer deze is ingesteld op een verwerkingssnelheid van 32000 samples/sec,
Dan kan een taak gewoon op volle snelheid draaien.
De taak wordt dan door de soundkaart in snelheid gelimiteerd waardoor de
uiteindelijke verwerkingssnelheid in realtime plaats vindt.
Voorwaarde is natuurlijk wel dat de verwerkende taak ten alle tijde over
voldoende rekenkracht kan beschikken.
Een voldoende snelle computer en bij voorkeur een eigen thread voor dit
process kan hier aan bijdragen.

de snelheid door


Fabeltjes
- Realtime vereist een snelle computer !
Nergens in de RealTime definitie staat dat zaken snel moeten gebeuren.
Voor realtime toepassingen is een nauwkeurig systeem nodig.
Een boot die met en snelheid van 25 Knopen de oceaan over vaart
heeft genoeg aan een positie bepaling van 1 berekening per seconde
Een ofset drukkerij die heel veel grafische data moet verstouwen
zal een snelle machiene gebruiken

- MicroSoft Windows 2000 heeft een realtime optie !
Het moge duidelijk zijn dat MicroSoft windows niet aan de gestelde eisen
voldoet.
Het enige dat je met die optie kunt doen is je applicatie alle beschikbare
rekentijd geven maar zelfs dan heeft het besturingssysteem nog voorrang.
Om met Windows een realtime omgeving te creeeren zul je een realtime paket
moeten instaleren (en die bestaan inderdaad).

- Er is toch RT-Linux !
Ook RT-Linux maakt gebruik van een RealTime Task Scheduler.
Evenmin als MicroSoft Windows is Linux geschikt voor RealTime toepassingen.
RT-Linux vangt alle interupts (duidelijk zichbaar in /proc/interupts),
en handelt deze als kerneltaak af waneer daar tijd voor is.
De synchrone (realtime) taken worden als kerneltaak met prioriteit uitgevoerd.
De Asynchrone taken hebben het meeste weg van gewone userapplicaties.
de communicatie tussen beiden geschied dmv pipes.
Ook draaien alle usertaken dus met een lagere prioriteit.
Het moge duidelijk zijn dat deze werkwijze een fors nadelig effect op de
performance van het Linux systeem heeft.

- Ik ga ook RealTime applicaties schrijven !
Veel sucses !