Hn/VxWorks

**VxWorks** er eit kommersielt sanntidsoperativsystem (RTOS) som vert mykje nytta i industrielle datasystem. Det er millom anna kjent for å verta nytta i romfarkostane åt NASA.

Ålment hev me tri ulike slag operativsystem: Monolittisk, layered eller klient-tenar. Sistnemnde kann avgrensast til ein mikrokjerne som tek seg av scheduling og synkronisering. Annan funksjonalitet er implementert i parallelle prosessar og trådar. Applikasjonane er klientar som kommuniserar gjenom systemkall til sovorne ”server tasks”. VxWorks er eit sovore OS.

### Wind-kjernen
Kjernen i VxWorks heiter Wind. Han tek seg av scheduling og synkronisering. Scheduleren er avbrotsdriven og preemptive med 256 ulike prioritetsnivå. Prioritet 0 er den høgste og 255 den lægste. Med systemkallet kernelTimeSlice() kann ein kontrollera um scheduleren skal nytta round-robin scheduling eller ikkje på tasks med same prioritetsnivå. Denne typen scheduling er til vanleg slegen av.

### Modularitet og skalabilitet
Etter det som stend i VxWorks-databladet, kann utviklaren velja millom meir enn 100 ulike ”options” og setja i hop sjølvstyrte konfigurasjonar. Individuelle modular kann skalerast inn og ut or systemet, og dette gjev utviklaren høve til å skreddarsy run-time-software for alskens applikasjonar. Til dømes kann individuelle funksjonar takast ut or ANSI C run-time-biblioteket, eller serskilde kjernesynkroniseringsobjekt kann takast ut um applikasjonen ikkje treng dei. 
I utviklingsfasen åt ein applikasjon kann det gjerne vera høvelegt å nytta netverkstenestor av ymist slag, medan det i den endelege utgåva vil verka ressurssparande å plukka burt denne funksjonaliteten. Då høver det godt at TCP, UDP, sockets og standard Berkeley netverkstenestor alle er døme på modular som kann skalerast inn eller ut or systemet.

### Utviklingsmetodikk
VxWorks-utviklarar byggjar på ”host != target”-prinsippet. Utviklingsmiljøet, kalla Tornado, held til på ein Windows NT eller Solaris arbeidsstasjon. Ein kann nytta host-maskinen til å redigera, kompilera, lekkja og lagra real-time-kode, og dinæst køyra og ”debugge” real-time-koden på target-maskinen. Den endelege VxWorks-applikasjonen kann køyra åleine på target-maskinen, anten i ROM eller på disk, utan nokon studnad frå netverket eller host-maskinen.

Host-maskinen og VxWorks-maskinen kann jamvel arbeida saman i ein hybrid-applikasjon der host-maskinen nyttar VxWorks-systemet som ein real-time-server i eit netverksmiljø. Til dømes kann eit VxWorks-system som styrer fabrikkutstyr taka imot instruksjonar frå ein host-maskin som køyrer NT.

### Studnad for [[C++]]:
Attåt generell studnad for C++, inkludert iostream-biblioteket og standard template library, fær du med den valfrie komponenten Wind Foundation Classes desse objektbiblioteki:
VxWorks Wrapper Class Library
Tools h++ library frå Rogue Wawe.

### Debugging:
Med i “Wind DeBug”-protokollen fylgjer ein sokalla “Target Agent”. Um ikkje anna vert spesifisert, køyrer han som ein eigen task kalla tWdbTask. Tornado-serveren sender debugging-fyrespurnader til agenten som fær høve til å kontrollera eller manipulera andre tasks i systemet.

### Multitasking/scheduling:
Multitasking gjev sanntidapplikasjonar høve til å fungera som eit sett sjølvstendige tasks. Kvar task hev sin eigen kontekst, det vil segja CPU-miljø og systemressursar som applikasjonen ser kvar gong han køyrer. Ved ein ”context switch”, dvs skifte frå ein prosess/tråd til ein annan, vert konteksten lagra i ein ”Task Control Block” (TCB). Kvar kontekst inneheld:

*	Ein programteljar (program counter)
*	CPU-register og um turvande floating-point register
*	Ein stabel (stack) med dynamiske variablar og returadressor til funksjonskall
*	IO-tilordningar for standard input, output, error
*	Eit forseinkingsur (delay timer)
*	Eit tidlukeur (timeslice timer)
*	Kjernekontrollstrukturar
*	Signalhandlers
*	Kontrollvariablar for debugging og yvervaking

Wind-scheduleren nyttar til vanleg prioritetsbasert preemptive scheduling. Med preemptive scheduling fær kvar task sin prioritet og kjernen sikrar at CPU’en er allokert til høgaste prioritetstask i ready-lista. Denne schedulingi er preemptive på den måten at um ein task med høgare prioritet vert ”ready”, lagrar kjernen straks konteksten til noverande task og svitsjar kontekst til tasken med høgare prioritet.

Med round-robin scheduling vert CPU-tidi likt fordelt millom alle ready-tasks med same prioritet. CPU-tilgangen gjeng på rundgang der kvar tasks køyrer i eit fastsett intervall eller ”time slice”.

Rutinen som kontrollerar round-robin-scheduleren er:

kernelTimeSlice(int ticks)

Wind-kjernen hev prioritetsnivå frå 0 og ned til 255. Tasks vert tilordna prioritet i det dei vert skapte, men ein kann byta prioritet undervegs med systemkallet taskPrioritySet().

Når ein task vert skapt, gjeng han inn i tilstandet ”Suspended”. Etter at han er skapt, lyt han aktiverast for å koma yver i ”Ready”-tilstandet. Eventuelt kann ein nytta ”Spawning”-primitiven som gjev høve til både skaping og aktivering med einskildfunksjonen taskSpawn().

Døme frå C++:
id = taskSpawn(name, priority, options, stacksize, function, arg1,.. , arg10);

Rutinen taskSpawn lagar her ein ny task context.

### Synkronisering:
VxWorks tilbyd både eigne wind-semaforar og POSIX-semaforar. Semaforar gjev dei ulike applikasjonane høve til å koordinera einannan. Den mest upplagde måten ulike tasks kann kommunisera på er gjenom ”shared memory”. Sidan alle tasks i VxWorks eksisterar i det same lineære adressevaldet, er det lett å byta datastrukturar. Globale variablar, lineære buffer, ringbuffer, lekkjelistor og peikarar kann refererast beinveges frå program som køyrer i ulik kontekst.

Kor som er lyt det finnast ein mekanisme som hindrar at programmi øydelegg for einannan. Ein av metodane som finst for å gjeva eit program eksklusiv ressurstilgang er bruk av semaforar.

Attåt POSIX-semaforane hev me tri slag semaforar i VxWorks, skreddarsydde for kvar sine uppgåvor:

Binær:
Den snøggaste og mest generelle semaforen. Utforma serskilt til synkronisering og jamvel mutual exclusion.

Mutual exclusion:
Ein serskild binær semafor, utforma serskilt til “mutual exclusion”, prioritetsarv (priority inversion), “deletion safety” og rekursjon.

Counting:
Som den binære semaforen, men held orden på kor mange gonger han vert frigjeven. Vaktar på ressursar det finst meir enn eitt næme av.

### Minnehandtering
I VxWorks køyrer all kode i det same lineære adressevaldet. Minneadressering treng soleides ikkje vera med i ”task context”. Skulde kvar task ha sitt eige minnevald, trong ein mapping frå virtuelt til fysisk minne, og det er berre tilgjengeleg gjenom den valfrie komponenten VxVMI.

Mange operativsystem tilbyd paging og swapping. I sanntids-OS kann me ikkje nytta sovorne teknikkar då det skaper uventa forseinkingar i programkøyringi. Sidan Wind-kjernen er serskilt utforma for sanntidsapplikasjonar, nyttar han aldri paging eller swapping. Kor som er held POSIX 1003.1b-standarden for sanntidsystem studnad for operativsystem med virtuelt minne. I sovorne system kann applikasjonar som nyttar POSIX page-locking hindra at utvalde blokker i minnet vert paga eller swappa. For skuld portabiliteten hev VxWorks inkludert page-locking-rutinane i POSIX. Det gjer ingen skilnad til eller frå um ein nyttar desse rutinane då alt minnet i praksis er ”locked”.

### Priority inversion control
Priority inversion fær me bruk for når ein task med høg prioritet vert tvinga til å venta på ein task med lægre prioritet. Det vanlegaste dømet på dette er at ein høgprioritetsprosess lyt venta på ein lågprioritetsprosess som held eit synkroniseringsobjekt (ein semafor). For å hindra at ein prosess med medium prioritet skal preempta den blokkerande lågprioritetsprosessen, vert lågprioritetsprosessen tilordna same prioritet som høgprioritetsprosessen.

For å kunna nytta priority inversion på ein “mutual exclusion”-semafor, lyt me nytta flagget SEM_INVERSION_SAFE som enablar ein prioritetsarvealgoritme. Denne algoritmen sikrar at prosessen som er inne i den kritiske regionen køyrer på same prioritetsnivå som prosessen han hev blokkert i denne regionen. So snart den prioritetsinverterte prosessen hev sleppt semaforen, fær han attende den upphavlege prioriteten sin. SEM_INVERSION_SAFE må nyttast i kombinasjon med flaget SEM_Q_PRIORITY.

Døme frå C++:
semId = semMCreate(SEM_Q_PRIORITY | SEM_INVERSION_SAFE);

### Avbrotshandtering
Avbrot (interrupts) gjev systemet høve til å ansa på eksterne hendingar. I VxWorks er kvar interrupt knytt til si Interrupt Service Routine (ISR) gjenom ein vektortabell. Programutviklaren kann sjølv skriva eigne ISRs og knyta deim til sine respektive interrupts med systemkallet intConnect().

Det som normalt hender når ein interrupt gjeng inn til systemet, er at ikkje-kritisk kode vert preempta og ISR’en køyrd. Tidi det tek frå interrupt-signalet når systemet til ISR’en køyrer kallar me interrupt latency. Sidan mange interrupts kann koma i snøgg rekkjefylgja og ISRs med høg prioritet kann blokkera ISRs med låg prioritet, er det viktugt å halda ISR-prosesseringi på eit minimum.

ISR-koden køyrer ikkje i vanleg task context, han hev ingen Task Control Block (TCB) og alle ISRs nyttar same stabelen (stack). Desse skilnadene fører med seg visse avgrensingar for kva slags rutinar som kann køyra frå ein ISR.

ISRs bør ikkje nytta funksjonar som kann føra at prosessen som kalla upp interruptet vert ”blokkert”. Døme på funksjonar som ikkje kann nyttast er malloc, free og semTake. Ein ISR må ikkje nytta IO-operasjonar gjenom VxWorks-systemet. Eit kall til ein device driver kann blokkera systemet um han som kalla upp interruptet lyt venta på devicen.

ISRs bør ikkje nytta floating point instructions då desse operasjonane er tidkrevjande og dei dedikerte registri ikkje er lagra i entryet åt eit ISR (Fyre eit interrupt vert kalla upp, pushar me ymse register på stacken slik at ISR’en ikkje skal skriva yver data som uppkallaren sidan skal nytta seg av. Dette kallar me entryet åt eit ISR. Motsett lyt me pop’a informasjonen attende fyre me returnerar kontrollen til uppkallaren).

### Intertask-kommunikasjon
VxWorks hev intertask-communication-mekanismar som gjev sjølvstendige tasks høve til å koordinera einannan. Utviklaren kann forma ut programmi med shared memory, meldingskøar, semaforar, events og pipes (For intertask-messaging innanfor CPU’en. Pipes er virtuelle IO-einingar styrte av driveren pipeDrv. pipeDevCreate() skaper ein pipe-device og den assosierte meldingskøen. Tasks vert blokkerte når dei les frå ein tom pipe eller skriv til ein full pipe. Til liks med vanlege meldingskøar kann ISR’ar skriva til ein pipe, men ikkje lesa frå ein pipe), sockets og remote procedure calls (til intertask-kommunikasjon yver netverk) og signals (til exception handling). For å kontrollera kritiske systemressursar er mange slag semaforar tilgjengelege – som alt nemnt under ”Synkronisering”.

Meldingskøar er den viktugaste mekanismen VxWorks hev for kommunikasjon millom tasks på same prosessor. Meldingskøane gjev høve til å utveksla meldingar av variabel lengd. Kvar einaste task kann senda meldingar eller taka imot meldingar. Dei same meldingskøane kann delast av mange tasks. Tvovegskommunikasjon millom tvo tasks krev til vanleg tvo meldingskøar, ein for kvar veg kommunikasjonen gjeng.

Wind-meldingskøar kann skapast og slettast med desse rutinane:
*	msgQCreate(int maxMsgs, int maxMsgLength, int options): Allokerar og initialiserar ein meldingskø. 
*	msgQDelete(MSG_Q_ID msgQId): Terminerar og frigjev ein meldingskø. 
*	msgQSend(MSG_Q_ID msgQId, char *Buffer, UINT nBytes, int timeout, int priority): Sender ei melding til ein meldingskø. Um ingen tasks ventar på meldingar frå køen, vert ho lagd til. Er tasks som ventar, gjeng meldingi beinveges åt den fyrste tasken som ventar.
*	msgQReceive(MSG_Q_ID msgQId, char *Buffer, UINT nBytes, int timeout) Tek imot melding frå ein meldingskø. Um det er meldingar tilgjengelege, vert den fyrste meldingi straks teki ut or køen og returnert til uppkallaren. Um ingen meldingar er tilgjengelege, vert uppkallaren blokkert.
Meldingskøane vert organiserte etter FIFO-prinsippet, men med eitt undantak: Det er tvo ulike prioritetsnivå, MSG_PRI_NORMAL og MSG_PRI_URGENT, og sokalla urgent-messages vert lagde til fremst i meldingskøen.
Både msqQSend() og msgQRecieve tek imot timeout parameter. Timeout-parameteren spesifiserar kor mange ticks (klokketikk per sekund) uppkallaren kann venta på svar.
Signal
Eit signal vert generert ved ei hending (”event”) og er ein software-notifikasjon til ein task. Signalet er levert når ein task reagerar på signalet. Livetidi åt eit signal er tidi frå det vert generert til det vert levert. Um eit signal som er generert, men enno ikkje levert, nyttar me nemningi ”pending”.

I VxWorks kann alle tasks generera signal til andre tasks. Tasken som tek imot signalet suspenderar då straks tråden han køyrer i og let den task-spesifiserte signalhandlerrutina køyra næste gong tasken er ”scheduled” til å køyra. Signalhandleren fær køyra jamvel um den aktuelle tasken er blokkert. Signalet kann soleides nyttast til asynkron yverføring av kontroll. Signalhandleren er ei brukardefinert rutine som er knytt til eit serskilt signal. Signal høver best til error og exception handling, helder enn vanleg intertask-kommunikasjon.

Wind-kjernen hev både BSD 4.3 og POSIX signal interface. POSIX-interfacen tilbyd eit standardisert grensesnitt som det heiter seg er meir funksjonelt enn BSD 4.3 interface.

VxWorks hev signalsett med 31 serskilde signal. Eit signal kann genererast med rutinen kill(), han svarar til eit interrupt eller ein hardware exception. Ein signalhandler knyter seg til eit serskilt signal med funksjonen sigaction(). Når signalhandleren køyrer, er andre signal blokkerte frå å levera. Tasks kann blokkera mot visse signal med rutinen sigprocmask(). Um eit signal er blokkert i det det vert generert, vert signalhandleren kalla upp att når signalet ikkje lenger er blokkert.

Ein datastruktur av typen struct sigaction held handlerinformasjonen. Sigaction()-kallet hev tri parameter: Signalnummeret, ein peikar til den nye handlerstrukturen og ein peikar til den tidlegare handlerstrukturen (eventuelt nullpointer):

int sigaction(int signo, const struct sigaction *pAct, struct sigaction *pOact)

For å senda eit serskilt signal åt ein serskild task, hev me som alt nemnt systemkallet kill(int, int) der det fyrste argumentet er task id å senda signalet åt, det andre er nummer på signalet me sender åt tasken.

### POSIX-kompatibilitet
VxWorks styd Posix 1003.1b, 1003.1c og grunnleggjande systemkall i 1003.1-spesifikasjonen, inkludert prosessprimitivar, filer og katalogar, I/O-primitivar, språktenestor og kataloghandtering.

VxWorks styd dessutan dei endelege standardane åt POSIX 1003.1b Real-Time Extensions, inkludert asynkron I/O, counting-semaforar, meldingskøar, signal, memory management (page locking), og scheduling control. POSIX 1003.1c pThreads er standard i VxWorks. Til dømes er pthread_create ekvivalent med taskSpawn().

### Filsystem
VxWorks hev studnad for mange lokale filsystem med block devices (diskar). Desse devicane nyttar alle standard grensesnitt slik at ulike filsystem kann nyttast. Lokale filsystem for SCSI tape devices og ISO 9660 CD-ROM devices er ogso inkludert. I/O-arkitekturen åt VxWorks gjev høve til å ha mange ulike filsystem på det same VxWorks-systemet samstundes.

Filsystem som VxWorks tilbyd:

dosFs, kompatibelt med MS-DOS filsystem (upp til version 6.2). Diskettar og harddiskar (um dei er rett konfigurerte) laga i MS-DOS kann nyttast fritt. dosFS organiserar filer og katalogar hierarkisk og gjev høve til til å allokera filer samanhangande på disken. Med fysisk samanhangande filer vert filsystemet snøggare, men filer som ikkje heng i hop gjev meir effektiv bruk av diskplass. Case-sensitive filnamn utan (8+3)-avgrensingi er valfritt.

rt11Fs, kompatibelt med RT-11-operativsystemet. Filsystemet hev vorte nytta i sanntidsapplikasjonar med di alle filene er samanhangande. rt11Fs vantar diverre hierarkisk filorganisering som ein gjerne treng på store diskar. Allokeringsskjemaet åt rt11Fs er er reikna for nokso rigid og fører gjerne til at diskplassen vert fragmentert.

rawFS, eit einfelt ”raw disk file system”. rawFs handsamar disken mest som ei einaste stor fil. rawFs gjev løyve til å lesa og skriva til blokker på disken, spesifisert av ein byte offset. rawFs hev fyremunen at det arbeider snøggt.

tapeFs, SCSI Sequential File System. Dette er eit filsystem for tape devices som ikkje nyttar nokon standard fil- eller katalogstruktur på tapen. Tapen vert nytta som ein raw device der heile volumet er ei stor fil. All dataorganisering på denne store fili må gjerast på eit høgare nivå.

cdRomFs, ISO 9660 CD-ROM filsystem. Data kann aksesserast med standard POSIX I/O-kall.

### Asynkron IO
Asynkron IO (AIO) gjev høve til å køyra IO-operasjonar parallellt med onnor prosessering. Med AIO kann IO-operasjonane i ein prosess styrast av ein eigen ”handler” og fråkoplast andre aktivitetar som logisk sèt ikkje hev noko med einannan å gjera. Soleides slepp prosessane å verta blokkerte, slik dei gjerne vert med synkron IO. VxWorks hev implementert asynkron IO etter spesifikasjonen i POSIX 1003.1b.

### Netverk
VxWorks hævdar å vera det fyrste sanntids-OS’et som integrerte industri-standard TCP/IP-tenestor i sanntidsapplikasjonar. VxWorks styd i dag desse standardane:
BSD 4.4 TCP/IP-netverk
IP, IGMP, CIDR, TCP, UDP, ARP
RIP v1/v2
Standard Berkeley sockets, zbufs
SLIP, CSLIP
BOOTP, DNS, DHCP, TFTP
NFS, SUN RPC
FTP, rlogin, rsh, telnet
SNTP

### Klokkeuppløysing og timeruppløysing
VxWorks tilbyd POSIX 1003.1b-klokka. Denne sanntidsklokka kann me til dømes nytta som argument til POSIX-funksjonen nanosleep(). 
Klokkeuppløysingi er talet på system clock ticks per sekund. I VxWorks kann ein finna klokkeuppløysingi med systemkallet sysClkRateGet() eller POSIX-kallet clock_getres().
Klokkeuppløysingi kann me setja med rutina clock_setres().

VxWorks tilbyd mange ulike ”timing functions”. timex(), taskDelay(), kernelTimeSlice(), wdStart() er alle døme på funksjonar som baserar seg på system clock ticks, og som soleides skil seg på klokkeuppløysingi.

### Snøggleik
Rutinen timex() kann me nytta til å finna ut kor lang tid det tek å køyra ein spesifisert funksjon. Når funksjonen er ferdugt eksekvert, syner rutinen køyretidi og ein feilmargin i millisekund. Um eksekveringi gjekk so snøggt i høve til klokkerata at tidi er meiningslaus (error > 50 %), kjem det fram ei åtvaring. I so fall bør ein nytta rutinen timexN() som køyrer funksjonen so mange gonger at resultatet vert nokolunde pålitande.

Syntaks:
void timex(FUNCPTR function_name, int arg1, .., int arg8)

### Pris
VxWorks er ikkje billeg, og på news er det utviklarar som klagar yver at dei ikkje lenger hev råd å utvikla programvare på plattformi. Tek ein kontakt med WindRiver, er dei høgst uviljuge til å fortelja kva det kostar for ein lisens. I staden vil dei vita kva slags ”features” du hev bruk for og kor mange lisensar du vil ha.

### Studde arkitekturar
WindRiver hævdar å ha studnad for desse arkitekturane:
PowerPC, Intel 32-bit, MIPS, ARM, Motorola 68000, CPU32, ColdFire, MCORE, Intel i960, SH, SPARC, NEC v8xx, M32 R/D, RAD6000, ST 20 og TriCore.

### Kjeldor
* Øystein Ra, «Real Time Operating Systems», kompendium i digitale system, HIBU, 2002.
* comp.os.vxworks Frequently Asked Questions (FAQ)
* http://members.aol.com/karima4483/vxworks.html
* http://www-ece.engr.ucf.edu/~jza/classes/6897/web/RTtiming.pdf