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.
Réponses:
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.
la source
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.
la source
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:
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.
la source
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.
la source
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.
la source