64-битная точность Sleep function? - PullRequest
0 голосов
/ 08 февраля 2019

В настоящее время Сон принимает один DWORD (32 бита) для времени.Есть ли альтернатива, которая принимает DWORDLONG (64 бита)?

Я использую RNG, в которой с каждым добавленным дополнительным байтом общее время ожидания увеличивается.С 32-разрядным целым числом общее время составляет 5 минут, и я хочу увеличить его.

Ответы [ 3 ]

0 голосов
/ 08 февраля 2019

Sleep() занимает миллисекунды.Максимальное значение DWORD, 4294967295, приведет к периоду ожидания 49,7 дня.Для большинства целей это достаточно хорошее максимальное значение, но если вы определились с 64-битным параметром сна, вы можете объединить несколько вызовов Sleep() вместе.Это изменит максимальное количество миллисекунд, на которое вы можете Sleep(), на 18446744073709551615, что составляет порядок сотен тысяч веков:

VOID WINAPI Sleep64(DWORDLONG dwlMilliseconds)
{
    while (dwlMilliseconds)
    {
        Sleep(min(0xFFFFFFFE, dwlMilliseconds));
        dwlMilliseconds -= min(0xFFFFFFFE, dwlMilliseconds);
    }
}

Я проверил это и могу убедиться, что оноработы.

0 голосов
/ 08 февраля 2019

Sleep[Ex] внутренний вызов NtDelayExecution - не документирован, но существует во всех версиях Windows NT (от NT 4 до Win 10) - экспортируется ntdll.dll - использовать ntdll.lib или ntdllp.lib из wdk.В результате этого вызова в ядре будет вызываться документированная функция KeDelayExecutionThread

//extern "C"
NTSYSAPI 
NTSTATUS
NTAPI
NtDelayExecution(
  IN BOOLEAN              Alertable,
  IN PLARGE_INTEGER       Interval );
  • Alertable

Указывает ИСТИНА , если ожидание оповещено.Драйверы нижнего уровня должны указывать FALSE .

  • Интервал

Указывает абсолютное или относительное время в единицах 100наносекунды, для которых должно произойти ожидание.Отрицательное значение указывает относительное время.Абсолютное время истечения отслеживает любые изменения системного времени;относительное время истечения не зависит от изменения системного времени.

Sleep[Ex] - оболочка win32, поверх этого собственного API, который ограничивает значение интервала (от 64 до 32 бит), не может установить абсолютное время (возможно)с NtDelayExecution) и игнорировать оповещения (мы можем выйти из NtDelayExecution через поток оповещений, если ожидается оповещение)

, так что вы можете напрямую вызывать этот API вместо косвенного через Sleep[Ex]

, так что Sleep(dwMilliseconds)это вызов Sleep(dwMilliseconds, false)

SleepEx(dwMilliseconds, bAlertable) 

вызов

LARGE_INTEGER  Interval;
Interval.QuadPart = -(dwMilliseconds * 10000);
NtDelayExecution(bALertable, &Interval);

обратите внимание, что в случае ожидаемого ожидания он может быть прерван через apc (api return STATUS_USER_APC) или через оповещение (STATUS_ALERTEDбудет возвращен. Мы можем предупредить поток через NtAlertThread).SleepEx проверяет возвращенное состояние, а в случае STATUS_ALERTED - снова начинает ожидание с обновленным интервалом.поэтому SleepEx ожидание не может быть прервано с помощью оповещения (NtAlertThread), но NtDelayExecution может

0 голосов
/ 08 февраля 2019

Есть ли альтернатива, которая принимает DWORDLONG (64 бита)?

Нет.Вам понадобится несколько звонков на Sleep в цикле.

Удачного тестирования и отладки многомесячного сна.

...