Comment se fait-il que les RTOS soient considérés comme déterministes?

8

Sur un PC (un OS bien sûr) tout programme C devient indéterministe en termes de timing. Par exemple, une boucle prend entre 1,2 et 1,3 secondes selon "la vitesse à laquelle je déplace une autre fenêtre". C'est parce que le système d'exploitation fait que les processus (ou threads) partagent la puissance de traitement.

En ce qui concerne les RTOS (sur un système embarqué), lorsque nous écrivons une application multithreading, je pense que la même chose se produit en fonction du nombre de threads exécutés simultanément.

Je n'ai pas d'instruments pour tester cela avec précision sur un système embarqué. Ainsi, je voulais demander. Ma préoccupation est-elle raisonnable ou manque-t-il quelque chose de très fondamental?

EDIT : Je vais donner un exemple. nous avons task1 (prend 10 ms) et task2 (prend 20 ms). Ils ont commencé en même temps sur deux threads séparés. Ma réclamation (également préoccupante, pas sûre) est que task1 prend plus de 10 ms, car ils partagent la puissance de traitement avec task2.

ozgur
la source
Le déterminisme comprend l'ensemble (et le timing) des entrées
PlasmaHH
3
Il vous manque la définition de RTOS. ;-)
DrFriedParts
1
Un RTOS n'est pas utilisé pour exécuter des tâches individuelles qui doivent répondre à des exigences de synchronisation individuelles, il est utilisé pour exécuter un système qui doit, dans son ensemble, répondre à toutes ses exigences de synchronisation. Déterministe ne signifie pas «indépendant de toutes les circonstances», cela signifie «quand je connais suffisamment les circonstances (qui inclut certainement les tâches de priorité plus élevée), je peux prédire une limite supérieure».
Wouter van Ooijen

Réponses:

6

Ce n'est pas vrai que les tâches dans un RTOS sont automatiquement déterministes, mais il est possible d'imposer des contraintes beaucoup plus strictes sur le moment et la fréquence d'exécution des tâches. Un RTOS fournira généralement des priorités strictes pour les tâches; à tout moment la tâche prête avec la priorité la plus élevée est en cours d'exécution. L'auteur du code a également un contrôle total sur l'ensemble des tâches en cours d'exécution; vous pouvez raisonnablement vous attendre à ce qu'aucune tâche d'arrière-plan de haute priorité n'interrompe votre code pour, par exemple, échanger des données sur le disque, sauf si vous les avez écrites.

En plus de cela, certains RTOS prévoient un multitâche coopératif. Contrairement au multitâche préemptif, avec le multitâche coopératif, une tâche continuera de s'exécuter jusqu'à ce qu'elle abandonne volontairement le contrôle du CPU.

Nick Johnson
la source
10

En ce qui concerne les RTOS (sur un système embarqué), lorsque nous écrivons une application multithreading, je pense que la même chose se produit en fonction du nombre de threads exécutés simultanément.

NAN!

Si cela se produit, ce n'est pas un système d'exploitation en temps réel (RTOS).

La réponse courte est que la définition d'un RTOS n'a rien à voir avec le multitâche ou la priorité. C'est simplement que toutes les tâches ont des garanties de timing .

Le reste de ce que vous considérez comme les caractéristiques d'un RTOS (hiérarchisation, achèvement des tâches, etc.) ne sont que des conséquences (ou des fonctionnalités) de la construction d'un système où les tâches doivent se terminer dans l'intervalle de temps spécifié.

Le multitâche dans un RTOS est conceptuellement plus simple que dans un OS à temps doux, car la plupart des cas de bord compliqués ne sont essentiellement pas autorisés.

DrFriedParts
la source
Donc, si task1 prend 10 ms et task2 prend 20 ms séparément. S'ils s'exécutent en même temps (en tant que deux threads séparés), seraient-ils toujours complets en 10 ms et 20 ms respectivement?
ozgur
2
En effet, tout l'intérêt d'un RTOS est de faire en sorte que les tâches de faible priorité ne s'exécutent pas simultanément avec les tâches de haute priorité.
pjc50
1
@ pjc50 - Je pense que votre commentaire est le point critique qui se perd peut-être. La question contient un malentendu fondamental. Il n'y a pas de «tâche 1 démarrée et tâche 2 démarrée en même temps »; une tâche de priorité plus élevée (T1) arrêtera / préemptera une tâche de priorité inférieure (T2) jusqu'à ce que T1 soit terminée, ou elle sera préemptée par une tâche de priorité encore plus élevée (T0). De toute évidence, aucun système d'exploitation ne peut magiquement permettre des tâches qui nécessitent plus que les ressources disponibles pour répondre à leurs contraintes de temps, d'espace, etc.
gbulmer
2
"aucun système d'exploitation ne peut magiquement permettre des tâches qui nécessitent plus que les ressources disponibles" - En effet, il ne le peut pas. Mais un vrai RTOS vous permettra de savoir à l' avance s'il est garanti que toutes vos contraintes seront respectées.
JimmyB
1
@ozgur: vous vous méprenez sur les applications qui s'exécutent sur RTOS. Au lieu d'avoir deux tâches qui prennent 10 ms et 20 ms, les applications sur RTOS ont généralement des tâches qui prennent 0,01 ms chacune, mais la tâche 1 doit exécuter TOUS les 10 ms et la tâche 2 doit exécuter TOUS les 20 ms. Habituellement, dans les applications en temps réel, nous ne permettons jamais aux threads de s'exécuter en parallèle pour partager la puissance du processeur. Au lieu de cela, nous exécutons un thread pendant le temps le plus court possible, puis le laissons dormir. Le but du RTOS est qu'il y a des garanties que lorsque je lui demande de me réveiller en 10 ms, il le fera au lieu de 10.01 ms
slebetman
6

Un RTOS ne garantit généralement pas le débit , mais il vous permet de garantir la latence .

Ceci est généralement réalisé par un système prioritaire, comme ici dans FreeRTOS:

Le planificateur FreeRTOS garantit que les tâches à l'état Prêt ou En cours d'exécution auront toujours du temps processeur (CPU) de préférence aux tâches de priorité inférieure qui sont également à l'état prêt. En d'autres termes, la tâche placée dans l'état En cours d'exécution est toujours la tâche de priorité la plus élevée pouvant être exécutée.

Supposons que vous ayez une tâche de priorité 1 qui prend 10 ms pour gérer un événement, une tâche de priorité 2 qui prend 100 ms pour gérer un événement différent et une tâche de priorité 3 en arrière-plan. Si vous prévoyez d'obtenir un événement de priorité 1 pas plus que chaque seconde, vous pouvez dire que le pire des cas pour gérer un événement de priorité 2 est 10 ms + 100 ms. La tâche de priorité 3 peut être arbitrairement ralentie par des événements, mais vous ne vous en souciez pas, car sa priorité est faible.

pjc50
la source
Dans votre exemple, la tâche de priorité 1 et la tâche de priorité 2 s'exécutent-elles en même temps (deux threads démarrés en même temps)?
ozgur
1
Potentiellement oui, ou la priorité 1 démarre alors que la priorité 2 est en cours d'exécution. Cet exemple suppose un seul processeur. Notez que l'exemple de spécification limite également la quantité de la tâche P1 qui peut s'exécuter - si vous obtenez un événement P1 toutes les 10 ms et que cela prend 10 ms à gérer, rien d'autre ne s'exécutera jamais .
pjc50
D'accord, voici ma question. task1 (10ms) a démarré en même temps que task2 (100ms) a démarré. Je crois que task1 prend plus de 10 ms car ils partagent la puissance de traitement avec la tâche 2. J'espère que je me suis bien fait comprendre.
ozgur
Je pense que le point soulevé est que le planificateur n'exécutera pas les tâches 1 et 2 en même temps. Il exécutera la tâche 1 (priorité plus élevée) en premier et mettra en file d'attente la tâche 2. 10 ms plus tard, lorsque la tâche 1 sera terminée, il exécutera la tâche 2.
michaelyoyo
1
Oui, il n'entrelacera pas l'exécution de task1 et task2. Si une tâche P1 est exécutable, aucune tâche P2 ne sera planifiée jusqu'à ce qu'elle soit terminée. Si une tâche P2 est déjà en cours d'exécution, elle sera anticipée et mise en pause jusqu'à ce que tout le travail P1 soit terminé.
pjc50
4

Je préfère que ce soit un commentaire mais qu'il faut trop de caractères. Quoi qu'il en soit, ozgur, à en juger par les questions dans vos réponses aux commentaires, vous semblez manquer le point que vous ne pouvez pas simplement dire que mon fil prend autant de temps à fonctionner et s'attendre à ce qu'il fonctionne comme par magie avec d'autres threads, tout cela grâce au système d'exploitation. Vous devez concevoir vos threads et les analyser pour les performances les plus défavorables. Si le pire des cas ne répond pas à vos exigences, vous devez repenser vos threads.

Donc, plutôt que de simplement dire que le thread 1 prend 10 ms pour terminer et que le thread 2 prend 20 ms, vous devez également dire que le thread 1 doit s'exécuter toutes les 15 ms. le thread 2 doit s'exécuter toutes les 40 ms. le thread 3 doit s'exécuter toutes les 500 ms, le threadN doit s'exécuter toutes les 1500 ms. Ensuite, vous allouez le temps nécessaire à l'exécution de chaque thread dans le pire des cas. Vous mettez tout cela ensemble, identifiez les pires scénarios possibles, puis vous devez vous assurer que chaque thread répond à ses exigences de synchronisation. Cette analyse est également l'endroit où vous identifiez si certains threads doivent avoir une priorité plus élevée que d'autres afin de répondre à leurs exigences de synchronisation.

Par exemple, thread5 est en cours d'exécution est interrompu par le thread 4 qui est interrompu par le thread 3 qui est interrompu par threadN pourrait être le pire des cas. Vous mettez tout cela sur une chronologie et vérifiez que même dans le pire des cas, chaque thread répond à ses exigences de synchronisation. Vous pouvez vous assurer que les threads terminent ce pire scénario de manière déterministe en utilisant le planificateur et les priorités dans un système d'exploitation en temps réel. Ce déterminisme est ce qui fait un système d'exploitation en temps réel.

Si vous faites des threads la même priorité, vous avez perdu une partie (sinon la totalité) de ce déterminisme car le planificateur peut être libre de choisir le thread qu'il souhaite exécuter ensuite.

Dans un système d'exploitation comme Windows, non seulement vous ne pouvez pas spécifier quand chaque thread s'exécutera, vous ne pouvez même pas garantir que votre application sera exécutée à tout moment. Le système d'exploitation peut arrêter votre application et exécuter un service d'arrière-plan à tout moment. En d'autres termes, il n'y a pas de déterminisme. Ainsi, Windows n'est pas un système d'exploitation en temps réel. Bien que, si vos exigences de synchronisation sont grandes, comme (thread1 s'exécute toutes les 10 secondes, thread2 s'exécute toutes les 15 secondes), vous pouvez essentiellement traiter Windows comme un système d'exploitation en temps réel tant que vous tenez compte de la pente et environ toutes les 10 ou 15 secondes (donner ou prendre quelques centaines de millisecondes et une fenêtre manquée occasionnelle) est assez bon.

Tremper
la source
1

Bien que d'autres réponses aient déclaré que dans le "monde réel" votre scénario n'est pas possible, pour pouvoir répondre à votre question, nous devons construire un système hypothétique .

Notre système se compose d'un pistolet qui tire des balles à un rythme régulier, de deux boîtes qui "attrapent" les balles et avancent d'un pas avec chaque balle capturée. Le pistolet peut être commuté pour tirer sur l'une des cases mais il perd une balle à chaque fois qu'il est commuté. La première boîte aura besoin de 1000 étapes (balles) pour atteindre sa fin et la boîte 2 aura besoin de 2000.

Scénario 1 (tâches les unes après les autres):
- le pistolet tire 1000 balles à la case 1, commute (coûte 1 balle) et tire 2000 balles à la case 2, pour un total de 3001 balles .

Scénario 2 (tâches "simultanées"):
- le pistolet tire 5 balles sur une case, commute et tire 5 balles sur l'autre case pour donner l' apparence de la simultanéité . Le coût de commutation est de (1000/5 x 2 =) 400 balles. Ainsi, après avoir tiré 2400 balles, la case 1 atteindra sa fin et la case 2 aura besoin de 1000 balles supplémentaires pour atteindre sa fin, pour un total de 3400 balles .

En appliquant ces résultats à votre scénario, la tâche 1 et la première moitié de la tâche 2 se termineraient après 24 ms, et la seconde moitié de la tâche 2 se terminerait en 10 ms supplémentaires pour un total de 34 ms. Cela montre clairement que le temps nécessaire pour terminer les tâches augmente en raison du temps perdu à basculer entre les tâches . Ces résultats sont également équivalents à la tâche 1 en 12 ms et à la tâche 2 en 22 ms.

Guill
la source
A voté. Cette explication a rendu ma question plus claire et la réponse est évidente.
ozgur