Linux, timerfd précision
J'ai un système qui a besoin d'au moins 10 mseconds de précision pour le timer.
Je suis allé pour timerfd comme il me convient parfaitement, mais a constaté que, même pour des temps jusqu'à 15 millisecondes il n'est pas précis du tout, ou alors je ne comprends pas comment il fonctionne.
Fois j'ai mesuré ont été jusqu'à 21 mseconds sur 10 mseconds minuterie.
J'ai mis en place un test rapide qui montre mon problème.
Voici un test:
#include <sys/timerfd.h>
#include <time.h>
#include <string.h>
#include <stdint.h>
int main(int argc, char *argv[]){
int timerfd = timerfd_create(CLOCK_MONOTONIC,0);
int milliseconds = atoi(argv[1]);
struct itimerspec timspec;
bzero(&timspec, sizeof(timspec));
timspec.it_interval.tv_sec = 0;
timspec.it_interval.tv_nsec = milliseconds * 1000000;
timspec.it_value.tv_sec = 0;
timspec.it_value.tv_nsec = 1;
int res = timerfd_settime(timerfd, 0, &timspec, 0);
if(res < 0){
perror("timerfd_settime:");
}
uint64_t expirations = 0;
int iterations = 0;
while( res = read(timerfd, &expirations, sizeof(expirations))){
if(res < 0){ perror("read:"); continue; }
if(expirations > 1){
printf("%lld expirations, %d iterations\n", expirations, iterations);
break;
}
iterations++;
}
}
Et exécutée comme ceci:
Zack ~$ for i in 2 4 8 10 15; do echo "intervals of $i milliseconds"; ./test $i;done
intervals of 2 milliseconds
2 expirations, 1 iterations
intervals of 4 milliseconds
2 expirations, 6381 iterations
intervals of 8 milliseconds
2 expirations, 21764 iterations
intervals of 10 milliseconds
2 expirations, 1089 iterations
intervals of 15 milliseconds
2 expirations, 3085 iterations
Même en supposant que certains retards éventuels, les 15 millisecondes retards des sons trop pour moi.
- Mes données à propos de la région sont assez rouillé. Les sons que vous voulez faire quelque chose en temps réel. Vérifiez en temps réel Linuxes. Sinon, le planificateur utilise plus les niveaux de granularité pour éviter des frais généraux. Vous souhaitez lancer votre processus de RT (real time) un (
man sched_setparam
) et probablement sous la racine. Pour les processus normaux (par exemple, des jeux ou multimédia), vous n'avez (1) en attente dans la boucle serrée, ou (2) sur chaque événement de minuterie calculer l'erreur (prévu v. réelle de l'heure de réveil) et prendre en compte lors de l'avancement à l'interne temps-dépendante de l'etat. - Merci pour l'astuce, mais je ne considère pas 20 intervalles de milliseconde dans le cadre de la fonction de domaine. Je veux dire, un système standard qui est demandé d'attendre 10 millisecondes ne devrait jamais attendre 21 millisecondes, RT sons trop pour cela.
- vous pouvez essayer le réglage de votre programme à exécuter avec priorité en temps réel, vous n'avez probablement pas besoin d'utiliser le RT noyau Linux de la canalisation principale est assez bon dans en temps réel de ces jours, et étant donné qu'il n'a jamais manqué plus d'une expiration juste en cours d'exécution avec la RT, la priorité devrait être suffisant pour vous de ne jamais manquer un
- en outre, vous devriez envisager de la météo ou pas, vous ne peut absolument pas tolérer le manque d'un réveil, si vous pouvez vous manquez parfois, ne vous inquiétez pas ça va arriver, mais ce n'est pas la fin du monde, vous aurez la plupart d'entre eux cependant. Je suis en cours d'exécution sur mon système et il n'a pas manqué une minuterie sur le 4ms en boucle encore et j'ai été en cours d'exécution pendant un certain temps maintenant...
- des intervalles de 2 millisecondes 2 expirations, 4282 itérations intervalles de 4 millisecondes 2 expirations, 149022 itérations cela fait donc environ 6 minutes avant qu'il manquait un wakup pour moi, de sorte que votre système est surchargé, lent, ou vous avez besoin de changer la configuration de votre noyau pour vous donner une meilleure minuteries
- Jimenez: temps Réel renvoie à avoir des exigences strictes, de ne pas réellement de limite inférieure sur la précision. Il ya beaucoup de choses que l'effet de la rapidité de la minuterie de livraison, y compris la version de Linux (le noyau) que vous utilisez, la configuration, il a été compilé avec le matériel que vous utilisez, et quoi d'autre est en cours d'exécution sur le système.
- aussi votre boucle est allé pour plus de 2 heures sur ma machine avec l'intervalle réglé à 8ms sans manquer un délai,
Vous devez vous connecter pour publier un commentaire.
Essayer de le modifier comme suit, cela devrait assez bien garuntee qu'il ne raterez plus jamais un réveil, mais être prudent avec elle depuis l'exécution en temps réel priorité pouvez verrouiller votre dur de la machine si elle ne dort pas, aussi vous devrez peut-être mettre les choses en place, de sorte que votre utilisateur a la possibilité d'exécuter des trucs à la priorité en temps réel (voir
/etc/security/limits.conf
)Si vous êtes à l'aide de threads, vous devez utiliser
pthread_setschedparam
au lieu desched_setscheduler
.En temps réel n'est pas à propos de la faible temps de latence, c'est sur les garanties, RT signifie que si vous voulez vous réveiller exactement une fois chaque seconde sur le la seconde, vous, le planning normal ne vous donne pas de cela, il peut choisir de vous réveiller 100ms plus tard, parce qu'il avait un travail à faire à ce moment de toute façon. Si vous voulez vous réveiller toutes les 10ms et vous avez VRAIMENT besoin, vous devez définir vous-même exécuter un compte en temps réel de la tâche, le noyau va vous réveiller toutes les 10ms sans échec. À moins d'une priorité plus élevée en temps réel de la tâche est occupé à faire des trucs.
Si vous avez besoin pour garantir que votre réveil intervalle est exactement un certain temps, il n'a pas d'importance si c'est 1 ms ou 1 seconde, vous ne l'obtenez pas, sauf si vous exécutez un temps réel de la tâche. Il y a de bonnes raisons de le noyau va le faire pour vous (économie d'énergie est l'un d'eux, un débit plus élevé est un autre, il en existe d'autres), mais c'est dans les droits de le faire parce que vous n'avez jamais dit que vous avez besoin de meilleures garanties. La plupart des choses n'a pas besoin d'être aussi précis, ou le besoin de ne jamais manquer de sorte que vous devrait penser à si oui ou non vous avez vraiment besoin.
citant http://www.ganssle.com/articles/realtime.htm
Soft en temps réel est à peu près la même, sauf que manquer une date limite, bien que souhaitable, n'est pas la fin du monde (par exemple la lecture audio et vidéo sont mous en temps réel des tâches, vous ne voulez pas manquer l'affichage d'une image, ou du tampon, mais si vous le faites c'est juste un clin d'à-coup, et il vous suffit de continuer). Si ce que vous essayez de faire est "soft" en temps réel, je ne vous embêtez pas avec l'exécution en temps réel priorité, car il est généralement préférable d'obtenir vos réveils dans le temps (ou au moins proche).
EDIT:
Si vous n'êtes pas en cours d'exécution en temps réel, le noyau par défaut de donner tous les compteurs vous faites un peu de 'mou' de sorte qu'il peut fusionner votre demande pour vous réveiller avec d'autres événements qui se produisent à la fois proche de celui que vous avez demandé (c'est si l'autre événement est dans le cadre de 'mou' de temps, il ne vous réveiller au moment de la demande, mais un peu plus tôt ou plus tard, dans le même temps, il était déjà prévu de faire quelque chose d'autre, cela permet d'économiser l'énergie).
Pour un peu plus d'info voir Haut (mais pas trop haut) résolution délais d'attente et Minuterie de mou (remarque je ne suis pas sûr si l'une de ces choses est exactement ce qui est vraiment dans le noyau depuis deux articles sont sur la lkml liste de diffusion des discussions, mais quelque chose comme le premier on est vraiment dans le noyau.
J'ai un sentiment que votre test est très dépendant du matériel. Quand j'ai couru votre exemple de programme sur mon système, il est apparu pour s'accrocher à 1ms. Pour faire votre test à tous significatifs sur mon ordinateur, j'ai dû changer de quelques millisecondes à quelques microsecondes. (J'ai changé le multiplicateur de 1_000_000 à 1_000.)
(Un peu intéressant que j'ai eu la plus longue s'étend de 16 et 47 microsecondes, mais 17 et 48 ont été horribles.)
temps(7) a quelques suggestions sur les raisons de nos plates-formes sont donc différents:
Tous la 'résolution' lignes dans mon fichier /proc/timer_list sont 1ns sur mon (certes ridiculement puissant) x86_64 système.
J'ai décidé d'essayer de comprendre d'où le "point de rupture" est sur mon ordinateur, mais vous avez renoncé à 110 microseconde exécuter:
90 microsecondes a duré trois millions d'itérations avant il a échoué à quelques reprises; c'est 22 fois une meilleure résolution que votre tout premier test, je dirais donc que le droit matériel, 10ms ne devrait pas être n'importe où près de difficile. (90 microsecondes est de 111 fois une meilleure résolution de 10 millisecondes.)
Mais si votre matériel n'est pas de fournir de la minuterie pour les minuteurs de haute résolution, puis Linux ne peut pas vous aider sans avoir recours à SCHED_RR ou SCHED_FIFO. Et même alors, peut-être un autre noyau pourrait mieux vous fournir le logiciel minuterie soutien dont vous avez besoin.
Bonne chance. 🙂
Voici une théorie. Si HZ est fixé à 250 pour votre système ( ce qui est typique ), alors vous avez un 4 milliseconde la résolution du timer. Une fois que votre processus est remplacé par le planificateur, il est probable qu'un certain nombre d'autres processus vont être planifié et exécuté avant que votre processus est une autre tranche de temps. Ce qui pourrait expliquer que l'on voit de la minuterie de résolution du 15 au 21 millisecondes. Le seul moyen de contourner ce problème serait d'exécuter un noyau temps-réel.
La solution typique pour la haute résolution de timing sur la non-temps réel des systèmes est essentiellement occupé, attendez un appel à sélectionner.
En fonction de ce que le système est en train de faire, il peut être un peu lente à revenir à votre tâche. À moins d'avoir un "vrai" système en temps réel, il n'y a aucune garantie qu'elle le fera mieux que ce que vous voyez, même si je suis d'accord que le résultat est un peu décevant.
Vous pouvez (pour la plupart) d'éliminer cette tâche commutateur /planificateur de temps. Si vous avez de la puissance CPU (et de l'électricité!) de rechange, une brutale mais efficace solution serait une attente active spin boucle.
L'idée est de lancer votre programme dans une boucle serrée, qui interroge en permanence l'horloge pour l'heure qu'il est, et appelle ensuite votre code lorsque le moment est venu. Au détriment de la prise de votre loi sur le système très lent pour tout le reste et de chauffer votre CPU, vous allez vous retrouver avec des tâches de planification, qui est la plupart du temps sans coupure.
J'ai écrit un tel système, une fois sous Windows XP pour faire tourner un moteur pas à pas, en fournissant régulièrement espacés impulsions jusqu'à 40K fois par seconde, et il a bien fonctionné. Bien sûr, votre kilométrage peut varier.