10
votes

Comment obtenir une tickette précise de 1 ms sous WinXP

J'essaie d'appeler une fonction toutes les 1 ms. Le problème est, j'aime faire avec les fenêtres. J'ai donc essayé l'API multimediatimer.

Multimediatimer API h2>

Source p>

hTimerQueue = CreateTimerQueue();
if(hTimerQueue == NULL)
{
printf("Error creating queue: 0x%x\n", GetLastError());
}

BOOL res = CreateTimerQueueTimer(
&hTimer, 
hTimerQueue, 
TimerProc, 
NULL, 
0, 
1,  // 1ms
    WT_EXECUTEDEFAULT);


9 commentaires

+1 parce que tout le monde aime les graphes soignés :)


Vous avez des attentes assez élevées de Windows.


@Bob Moore a ajouté une réponse qui contenait cette lien . La réponse a été supprimée, mais j'ai trouvé le lien une lecture intéressante sur des problèmes de policage dans les systèmes d'exploitation (les vrais OS sont des fenêtres anciennes, mais les concepts s'appliquent toujours toujours aux versions actuelles)


Timeetevent () crée un très bonne minuterie. Mais il ne peut pas préempter un fil de noyau hautement prioritaire.


@Hans: merci! C'est alors la raison de la bosse à environ 2 ms? Drôle, c'est que la distribution n'est pas plus randm mais discrète la double quantité de temps.


@schoe: Ce n'est pas mon expérience, je ne l'ai jamais vue que gigue.


SCHOETBI: sur XP, vous allez avoir des conducteurs qui désactivent les interruptions pour des centaines de millisecondes à la fois. Heck, plusieurs cartes mères suspendront le système d'exploitation pour des millisecondes. Essayer d'obtenir Isoch à ce niveau de résolution est très difficile sur un système d'exploitation général. Vista et Win7 ont facilité la tâche d'obtenir Isoch mais ils ne sont toujours pas parfaits.


Où est passé le graphique?


@Arno: semble que l'image Hoster a supprimé les graphiques.


3 Réponses :


6
votes

sans aller à un système d'exploitation en temps réel, vous ne peut pas Attendez-vous à avoir votre fonction appelée chaque 1 ms.

sous Windows qui n'est pas un système d'exploitation en temps réel (pour Linux, il est similaire), un programme qui lit à plusieurs reprises une heure actuelle avec la précision microseconde et stocke des différences consécutives dans un histogramme ayant une corramme non vide pour> 10 ms ! Cela signifie que parfois vous aurez 2 ms, mais vous pouvez également obtenir plus entre vos appels.


3 commentaires

Qu'est-ce que vous voulez dire exactement avec une corbeille non vide pour> 10ms? Voulez-vous dire que l'obtention du temps prend plus de 10 ms?


C'est correct. Ne rien faire mais appeler deux fois une fonction pour obtenir le temps entraîne une différence de temps supérieure à 10 ms. Très rare, une fois chaque minute ou heure selon l'ordinateur, mais arrive!


Un système d'exploitation Time non réel ne fournit pas de garanties de synchronisation, mais cela ne signifie pas que vous êtes assuré d'obtenir de longs retards. Il est souvent possible de contrôler étroitement le travail de telle sorte que vous ayez une probabilité très élevée, c'est-à-dire de la certitude de votre travail en temps opportun. Bien que je pense que la question ici a plus à voir avec la granularité et la performance de la minuterie qu'avec le temps réel.




1
votes

Un appel à NTQuérytimerresolution () retournera une valeur pour réticente . Dans votre cas, la résolution réelle est presque certainement 0,9765625 MS. C'est exactement ce que vous montrez dans la première parcelle. La deuxième occurrence d'environ 1,95 ms est plus précise dormir (1) = 1,9531 ms = 2 x 0,9765625 ms

Je suppose que la période d'interruption fonctionne à proximité de 1 ms (0,9765625).

Et maintenant, le problème commence: les signaux de la minuterie lorsque le délai souhaité expire.

dire que le réticalresolution est défini sur 0.9765625, le rythme cardiaque d'interruption du système fonctionnera à 0,9765625 MS ou 1024 Hz et un appel à Sleep est fait avec un retard de 1 ms. Deux scénarios doivent être examinés:

  1. L'appel a été fait <1ms (ΔT) devant la prochaine interruption. La prochaine interruption ne confirmera pas que la période de temps souhaitée a expiré. Seule l'interruption suivante entraînera le retour de l'appel. Le retard de sommeil résultant sera ΔT + 0,9765625 MS.
  2. L'appel a été fait> = 1 ms (ΔT) avant la prochaine interruption. La prochaine interruption forcera l'appel à revenir. Le retard de sommeil résultant sera ΔT.

    Donc, le résultat dépend beaucoup lorsque l'appel a été effectué et que vous pouvez donc observer des événements de 0,98 ms ainsi que des événements de 1,95 ms.

    edit: à l'aide de CreateTimerQueTimer poussera le délai observé à 1,95 car la tickette de la minuterie (période d'interruption) est de 0,9765625 MS. Lors de la première occurrence de l'interruption, la durée demandée de 1 MS n'a pas bien expiré, donc le TimerProc ne sera déclenché qu'après la deuxième interruption (2 x 0,9765625 ms = 1,953125 MS> 1 ms). Par conséquent, l'intrigue QueuTimer montre le pic à 1,953125 MS.

    Remarque: ce comportement dépend fortement du matériel sous-jacent.

    Plus de détails peut être trouvé sur le Projet horloge Windows


0 commentaires