7

この質問は、Windows (XP 以上) で何かを正確にタイミングすることに関するものではなく、callback または interrupt を介して非常に迅速に何かを行うことに関するものです。

1ミリ秒ごと、できれば100マイクロ秒ごとに何かを定期的に行う必要があります。私がする必要があるのは、この速度でいくつかの非同期ハードウェア (イーサネット) を駆動して、パケットの安定したストリームをネットワークに出力し、そのストリームが可能な限り定期的かつ同期的に見えるようにすることです。しかし、質問が(イーサネット)デバイスから分離できる場合は、一般的な答えを知っておくとよいでしょう。

「Windows を使用することさえ考えないでください!!!!」と言う前に、少し背景を説明します。すべてのリアルタイム システムに同じ要求があるわけではありません。平均して 10 ~ 16 ミリ秒ごとにオーディオまたは画像のブロックを処理する必要があるにもかかわらず、ほとんどの場合、曲とビデオは Windows で問題なく再生されます。適切なバッファリングを使用すると、Windows の遅延が変動する可能性がありますが、ハードウェアは遅延の影響をほとんど受けず、イベントの安定した同期ストリームを維持できます。それでも、私たちのほとんどは時折の不具合を許容します。私のアプリケーションはそのようなものです - おそらくかなり寛容です。

私にとって高価なオプションは、アプリケーション全体を Linux に移植することです。しかし、Linux は同じハードウェア上で動作する別のソフトウェアであるため、より優れたソフトウェアを作成し、Windows に固執することを強く好みます。競合するすべてのハードウェアとソフトウェアを排除できるという贅沢があります (インターネットやその他のネットワーク アクセスがない、他のアプリケーションが実行されていないなど)。Windows にこれを実行させる見込みはありますか? どのような制限がありますか?

ターゲット ハードウェアには高性能イベント タイマーがあり、このタイマーは割り込みをプログラムできることはわかっていますが、そのためのドライバーはありません。書いてもいいですか?そこに役立つ例はありますか?まだ見つかっていません。これは QueryPerformanceCounter に干渉しますか? イーサネット デバイスを使用するということは、select() を慎重に使用すればすべてが簡単になるということですか?

有用な記事へのポインタを歓迎します - 正確な時間を取得する方法についての概要を多数見つけましたが、忙しい待機に相当するものを使用する以外に、このようなことを行う方法についてはまだありません. 忙しい待ち時間を避ける方法はありますか?カーネル モードまたはデバイス ドライバー オプションはありますか?

4

4 に答える 4

5

マルチメディア タイマーを調べることを検討する必要があります。これらは、あなたが見ている解像度の種類を意図したタイマーです。

MSDNのこちらをご覧ください。

于 2011-08-10T00:52:42.647 に答える
0

プログラムの起動時にNtSetTimerResolutionを使用して、タイマーの解像度を設定します。はい、それは文書化されていない機能ですが、うまく機能します。NtQueryTimerResolutionを使用して、タイマーの解像度を知ることもできます(設定前と新しい解像度を設定した後)。

ヘッダーやLIBファイルで宣言されていないため、GetProcAddressfromを使用してこれらの関数のアドレスを動的に取得する必要があります。NTDLL.DLL

このようにタイマーの解像度を設定するとSleep、Windowsタイマー、現在の時刻を返す関数などに影響します。

于 2011-08-11T15:06:49.430 に答える
0

タイマーの粒度の問題が発生した場合は、スピンループで古き良きSleep()を使用することをお勧めします。基本的に、コードは次のようなことをする必要があります。

void PrecisionSleep(uint64 microSec)
{
    uint64 start_time;

    start_time = GetCurrentTime(); // assuming GetCurrentTime() returns microsecs

    // Calculate number of 10ms intervals using standard OS sleep.
    Sleep(10*(microSec/10000)); // assuming Sleep() takes millisecs as argument

    // Spin loop to spend the rest of the time in
    while(GetCurrentTime() - start_time < microSec)
    {}
}

このようにすると、高精度のスリープが得られ、それらの多くがスケジューリングの粒度(10msと想定)よりも大きい場合でも、CPUに大きな負担をかけることはありません。高精度のスリープを使用してパケットの時間を計測している間、パケットをループで送信できます。

ほとんどのシステムでオーディオが正常に機能する理由は、オーディオデバイスに独自のクロックがあるためです。オーディオデータをバッファリングするだけで、再生が処理され、バッファが空になるとプログラムが中断されます。実際、再生エンジンがCPUクロックに依存している場合、オーディオカードクロックとCPUクロックの間のタイムスキューが問題を引き起こす可能性があります。

編集:時間指定されたエントリのロック保護された最小ヒープを使用するスレッドを使用して、これからタイマーを抽象化できます(ヒープ比較は有効期限のタイムスタンプで行われます)。その後、callback()またはSetEvent()のいずれかを実行できます。次のタイムスタンプへのPrecisionSleep()が完了します。

于 2011-08-10T02:04:14.410 に答える
0

を使用して DirectX 9 を使用してこれを行いましたQueryPerformanceCounterが、タスクの切り替えによって混乱するため、少なくとも 1 つのコアを占有する必要があります。

ティアマーの良い比較については、次をご覧ください。

http://www.geisswerks.com/ryan/FAQS/timing.html

于 2011-08-10T00:58:01.540 に答える