Un sistema operatiu de temps real (RTOS) és un sistema operatiu (OS) que tracta de processar les dades tal com arriben de les aplicacions basades en temps real, per tant, sense retards en l'emmagatzematge. Els temps de processament dels dispositius amb RTOS són mesurats en dècimes de segons o fins i tot un període més petit.
El paradigma clau d'un RTOS que el diferencia dels sistemes operatius convencionals és el nivell de la seva consistència relativa a la quantitat de temps que es necessita per acceptar i completar la tasca d'una aplicació. Així doncs, aquest tipus de sistema no persegueix una gran capacitat de còmput, sinó més aviat una garantia per a poder complir les restriccions temporals subjectes a les aplicacions. D'aquesta manera es poden classificar en dos grups:
Hi ha dos termes fonamentals per entendre aquestes dues classificacions. El primer és el de "jitter" (fluctuació ràpida o tremolor).[1] o variabilitat existent, i el segon el de deadline, o requeriments temporals del dispositiu.
Un SO de temps real té un algorisme de planificació avançat. La flexibilitat del planificador permet una major orquestració del sistema informàtic pel que fa a la prioritat de processos, però un SO de temps real està dedicat més freqüentment a un conjunt limitat d'aplicacions. Els factors clau en un SO de temps real són les latències; la d'interrupció i la de commutació de fil. És recomanable que ambdues siguin mínimes tot i que un dispositiu de SO de temps real es valora més per la rapidesa o per com previsiblement pot respondre, que per la quantitat de treball que pot realitzar en un període determinat de temps.
Els dissenys més comuns en el campo dels RTOS són els següents:
Els primers dissenys de CPU necessitaven molts cicles per intercanviar les tasques, fet que significava una gran pèrdua de temps durant la qual la CPU no podia fer res més útil. Per exemple, amb un processador 68000 de 20 MHz, processador típic dels anys 80, els temps de commutació de tasques són aproximadament de 20 microsegons.(Per contra, una CPU ARM de 100 MHz, de l'any 2008, canvia en menys de 3 microsegons. A causa d'això, els primers sistemes operatius van tractar de minimitzar la pèrdua de temps de CPU, evitant canviar de tasca innecessàriament.[2]
En els dissenys més típics, una mateixa tasca té tres estats diferents:
La majoria de les tasques estan en l'estat ready o blocked la major part del temps, perquè generalment només pot haver una única tasca executant-se a la CPU alhora. El nombre d'elements a la cua de tasques preparades pot variar molt, depenent de la quantitat d'aquestes que el sistema necessita per executar-se i el tipus de planificador que utilitzi el sistema. En aquests tipus de sistemes multitasca no preferents, una tasca ha de renunciar al seu temps de còmput perquè s'executin altres tasques amb un deadline inferior.
En general, l'estructura de dades de la llista ready al planificador està dissenyat per minimitzar el temps emprat pel pitjor cas de la secció crítica del planificador, durant el qual no es té en compte la preferència i, en alguns casos, totes les interrupcions estan deshabilitades. De tota manera, l'elecció de l'estructura de dades depèn també del nombre màxim de tasques que poden haver en la llista ready.
Si algun cop hi ha un nombre considerable de tasques a la llista ready, la implementació d'una llista doblement enllaçada pot ser més adient. La llista ready normalment conté poques tasques, però és possible que passi que el número d'aquestes augmenti ocasionalment. Llavors caldrà que la llista sigui ordenada per prioritat perquè d'aquesta manera, la cerca de la tasca que té major prioritat no requerirà iterar a través de tota la llista. Per tant, inserir una tasca al planificador requereix recórrer la llista ready fins al final o fins que hi hagi una tasca de prioritat més baixa que la tasca inserida.
Cal tenir cura de no inhibir la preferència durant la cerca anteriorment mencionada, i és recomanable dividir les seccions crítiques més llargues en d'altres més petites. Si es produeix una interrupció que causa una tasca ready de major prioritat durant la inserció d'una tasca de més baixa prioritat, la primera pot inserir-se i executar-se immediatament abans d'inserir la segona.
El temps de resposta crítica, també anomenat temps de retorn, és el temps que triga la cua a donar una nova tasca ready i restaurar l'estat de la tasca de més alta prioritat. En un sistema RTOS ben dissenyat, llegir una nova tasca triga de 3 a 20 instruccions per cada entrada de la cua ready, i l'assignació de prioritat alta en una tasca ready pren de 5 a 30 instruccions.
En sistemes més avançats, les tasques de temps real comparteixen recursos de còmput amb moltes altres tasques sense requeriments temporals. En aquests sistemes, el planificador de la llista ready implementat com una llista enllaçada seria insuficient.
Els algoritmes més utilitzats pels planificadors per a sistemes operatius a temps reals són:
Els sistemes multitasques han de dirigir la compartició de dades i recursos hardware entre totes les tasques existents. Generalment, per a dues tasques no és segur accedir específicament a la mateixa dada o als mateixos recursos de forma simultània. Aquesta falta de seguretat fa referència al fet que el temps d'accés al recurs és inconsistent o impredictible. Hi ha tres enfocaments comuns per resoldre aquest problema:
Els sistemes operatius de propòsit general no permeten als programes d'usuari emmascarar/deshabilitar les interrupcions, ja que aquests programes poden controlar la CPU durant el temps que vulguin. Algunes CPUs modernes no permeten que el codi en mode usuari (espai d'usuari) deshabiliti les interrupcions, donat que es consideren un recurs clau dels sistemes operatius. Molts sistemes encastats i sistemes operatius, però, permeten que la mateixa aplicació s'executi en mode kernel per tenir un major control operatiu sense requerir la intervenció del sistema operatiu.
En els sistemes d'un sol processador, la metodologia que permet una solució amb la mínima sobrecàrrega per prevenir l'accés simultani dels recursos compartits són aquelles que permeten a les aplicacions executar-se en mode kernel i que poden emmascarar les interrupcions. Mentre les interrupcions estiguin emmascarades i la tasca actual no faci una crida bloquejant al sistema operatiu, la tasca actual té l'ús exclusiu de la CPU, ja que cap altra tasca pot interrompre-la per prendre el control, de manera que la secció crítica està protegida. Quan la tasca surt de la seva secció crítica ha de desemmascarar les interrupcions. L'emmascarament temporal de les interrupcions no hauria de ser utilitzat quan el camí més llarg a través de la secció crítica és més curt que la latència d'interrupció màxima desitjada. Normalment,aquest mètode de protecció només s'utilitza quan la secció crítica conté unes poques instruccions sense bucles. Aquesta metodologia és ideal per protegir el mapa de bits dels registres hardware quan els bits són controlats per tasques diferents.
Quan els recursos compartits han de ser reservats sense el bloqueig de totes les altres tasques (exemple del qual és l'espera de la memòria flaix per ser escrita), és millor utilitzar mecanismes disponibles en els sistemes operatius de propòsit general, com semàfors i la supervisió del SO de missatges entre processos. Aquests mecanismes involucren crides al sistema i normalment triga centenars d'instruccions d'execució a la CPU. En contraposició, les interrupcions d'emmascarament poden prendre el temps equivalent als que pren una instrucció en alguns processadors.
Un semàfor binari té dos estats possibles, el bloquejat i el no bloquejat. En el primer estat, les tasques han d'esperar al semàfor per desbloquejar-se. Aquest tipus de semàfor pot ser equivalent a un mutex. Normalment en una tasca es fixa un temps d'espera fins que el semàfor no ho canviï. Existeixen diversos problemes coneguts amb dissenys basats en semàfors, exemple dels quals poden ser els deadlocks i els algoritmes de prioritat.
En els algoritmes de prioritat, una tasca de prioritat alta esperarà que una tasca de prioritat baixa tingui un semàfor, però aquesta última no té prou temps de CPU per acabar la seva feina. Una solució típica és tenir una tasca que contingui un semàfor en execució, o “heretar” la prioritat més alta de la tasca d'espera. Però aquest enfocament tant simple falla quan hi ha diversos nivells d'espera: la tasca A espera a un semàfor binari bloquejat per la tasca B que, a la vegada, espera a un semàfor binari bloquejat per la tasca C. El tracte de múltiples nivells d'herència sense introduir inestabilitat en els cicles pot ser molt problemàtic i complex.
Un altre enfocament per a l'intercanvi de recursos són les tasques per enviar missatges en un pas de missatges organitzat. En aquest paradigma, el recurs és gestionat directament per una sola tasca. Quan una altra tasca vol interrogar o manipular el recurs, aquest envia un missatge a la gestió de tasques. Encara que el seu comportament en temps real és menys nítid que els sistemes de semàfors, els sistemes basats en missatges simples eviten la majoria de riscos d'estancament de protocol, i generalment es comporten millor que els sistemes de gestió de tasques basats en semàfors tot i que és possible que es produeixin problemes. La inversió de prioritats pot passar quan una tasca treballa en un missatge de baixa prioritat i fa cas omís d'un missatge de prioritat més elevada a la cua de missatges entrants. Es poden produir deadlocks de protocol quan dos o més tasques esperen entre si per enviar missatges de resposta.
Els controladors d'interrupcions solen mantenir-se el mínim temps possible, ja que els sistemes operatius a temps real són dissenyats per mantenir la latència dels processos. Aquests controladors posposen totes les iteracions amb el hardware el màxim temps possible; generalment l'únic que és necessari és informar del Acknowledgement o deshabilitar la interrupció, ja que d'aquesta forma no tornarà a succeir un altre cop quan el controlador retorna, i notificar a la tasca que ha d'acabar el treball. Això pot realitzar-se de diverses maneres, ja sigui desbloquejant el driver a través d'un semàfor, a través de flags o mitjançant pas de missatges. El planificador sovint proporciona la capacitat de desbloquejar una tasca quan es troba en un estat d'interrupció.
Un sistema operatiu manté catàlegs dels objectes que administra, exemple dels quals són els fils d'execució, les mutex, memòria, etc., i les actualitzacions d'aquests han de ser estrictament controlades. Per aquesta raó, pot ser problemàtic que un controlador d'interrupcions faci una crida a una funció del sistema operatiu (o crida de sistema) si l'aplicació també en fa una alhora. Les crides a funcions del sistema operatiu fetes pels controladors d'interrupcions podrien trobar l'objecte de la base de dades en un estat inconsistent perquè l'aplicació s'actualitza. Hi ha dos grans aproximacions per solucionar el problema: una arquitectura unificada i una arquitectura segmentada.
La reserva de memòria és un procés molt més crític en entorns de RTOS que d'altres sistemes.
Primerament, per l'estabilitat que no pot haver-hi leaks de memòria, o memòria que està reservada, que no s'utilitza i que mai s'allibera. El dispositiu ha de funcionar indefinidament de forma que no ha de tenir la necessitat de ser reinicialitzat. Per aquesta raó, la reserva de memòriadinàmica està mal vista i sempre que sigui possible s'ha de reservar tota la memòria que sigui necessària de forma estàtica en temps de compilació.
Una altra raó per la qual cal evitar la reserva de memòria dinàmica és la fragmentació de memòria. Aquesta situació podria donar-se en el cas de reservar i alliberar petits blocs de memòria d'un procés més gran, ja que en aquest cas els RTOS no poden reservar un gran bloc continu de memòria, encara que n'hi hagi de disponible. En segon lloc, la velocitat de l'assignació de memòria és important. Un esquema estàndard d'assignació de memòria és escanejar una llista enllaçada de mida indeterminada per trobar un bloc de memòria. Aquesta impredictibilitat no és permesa en sistemes RTOS degut a la prioritat d'aquests sistemes per a l'acompliment de les restriccions temporalsa les seves aplicacions. El mateix passa amb els discs mecànics, aquests tenen un temps d'accés molt més gran i més impredictibles que l'accés a memòria principal.
Els algoritmes de blocs de mida fixes funcionen prou bé per a sistemes encastats degut al poc soroll que aporta al sistema.
Un exemple comú d'aplicació RTOS és la recepció i mostreig de la HDTV, o televisió d'alta definició. Aquesta necessita llegir un senyal digital, descodificar-lo i mostrar-lo al ritme que arriben les dades. Qualsevol retard es veurà reflectit com si la imatge estigués pixelada o el moviment no fos continu.
D'acord amb un estudi realitzat el 2014 per EmbeddedMarketStudy, els següents RTOS són el top 10 dels sistemes operatius utilitzats en els mercat de sistemes encastats: