64位精度睡眠功能?
Posted
技术标签:
【中文标题】64位精度睡眠功能?【英文标题】:64bit precision Sleep function? 【发布时间】:2019-07-02 02:17:58 【问题描述】:目前Sleep 使用单个 DWORD(32 位)作为时间。有没有需要 DWORDLONG (64bit) 的替代方案?
我正在使用 RNG,其中每增加一个字节,总等待时间就会增加。使用 32 位整数,总时间为 5 分钟,我想增加它。
【问题讨论】:
不,但你为什么要睡超过 49.7 天? 嗯,这对初学者来说很安静 我没有连接到random.org
。
NtDelayExecution
取 PLARGE_INTEGER DelayInterval
所以 64 位值。这也可以是绝对的或相对的(从当前时间开始)
听起来越来越像一些疯狂的 XY 问题。
【参考方案1】:
是否有任何替代方案需要 DWORDLONG(64 位)?
没有。您需要循环多次调用Sleep
。
享受测试和调试多月睡眠的乐趣。
【讨论】:
或致电NtDelayExecution
啊,总有一个你知道的未记录的 API,@RbMm ;-)
但是Sleep[Ex]
内部调用NtDelayExecution
。这是本机 api 上的 win32 shell,它限制间隔值(从 64 位到 32 位)不能设置绝对时间(NtDelayExecution
可能)并忽略警报(如果等待警报,我们可以通过警报线程退出 NtDelayExecution
)
@RbMm 我猜你不欣赏我的幽默。哦,好吧。
对不起。根本不知道这里需要说什么:)【参考方案2】:
Sleep()
需要几毫秒。最大值 DWORD
值 4294967295 将导致 49.7 天的超时期限。对于大多数用途,这是一个足够好的最大值,但如果您确定要使用 64 位睡眠参数,则可以将多个 Sleep()
调用链接在一起。这会将您可以Sleep()
处理的最大毫秒数更改为 18446744073709551615,这是数十万个世纪的数量级:
VOID WINAPI Sleep64(DWORDLONG dwlMilliseconds)
while (dwlMilliseconds)
Sleep(min(0xFFFFFFFE, dwlMilliseconds));
dwlMilliseconds -= min(0xFFFFFFFE, dwlMilliseconds);
我已经对此进行了测试,并且可以验证它是否有效。
【讨论】:
你测试了多长时间? :) @JonathanPotter 那是个玩笑,Remy 对我帖子的编辑让其变得不那么明显(请注意原始帖子在那一行有剧透) 我也是 ;-)【参考方案3】:Sleep[Ex]
内部调用NtDelayExecution
- 未记录但存在于所有 Windows nt 版本(从 nt 4 到 win 10) - 由 ntdll.dll 导出 - 使用 ntdll.lib 或来自 wdk 的 ntdllp.lib。由于内核中的此调用将被称为记录函数KeDelayExecutionThread
//extern "C"
NTSYSAPI
NTSTATUS
NTAPI
NtDelayExecution(
IN BOOLEAN Alertable,
IN PLARGE_INTEGER Interval );
可提醒如果等待是可警告的,则指定 TRUE。较低级别的驱动程序应该 指定 FALSE。
间隔指定绝对时间或相对时间,以 100 纳秒为单位, 等待发生。负值表示相对 时间。绝对过期时间跟踪系统时间的任何变化; 相对过期时间不受系统时间变化的影响。
Sleep[Ex]
是 win32 shell,通过这个原生 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 返回 STATUS_USER_APC
)或警报(将返回 STATUS_ALERTED
。我们可以通过 NtAlertThread
警报线程来破坏。 SleepEx
检查返回的状态,如果STATUS_ALERTED
- 再次开始等待更新间隔。所以 SleepEx
等待不能通过警报 (NtAlertThread
) 打破,但 NtDelayExecution
可以
【讨论】:
负值又是什么意思? @AnArrayOfFunctions - 负值表示相对时间。所以确切地说,Sleep
只使用 64 位。说如果你想等待 1 秒 - 设置 DelayInterval.QuadPart = -10000000
如果你想等待无限 - DelayInterval.QuadPart = 0x8000000000000000
@AnArrayOfFunctions - 无论如何在内核中最终调用记录函数KeDelayExecutionThread
- 在这里阅读Interval
参数
顺便说一句,您对 APC 有何看法 - 我指定 bAlertable 为假。还有 KeDelayExecutionThread 和 ZwDelayExecution 有什么区别?
@AnArrayOfFunctions - 如果您将 bAlertable
设置为 false - 您的等待不能被 apc 或警报中断(这不是 apc)。用户模式下的NtDelayExecution
- 这是内核模式下NtDelayExecution
的存根。这个api调用KeDelayExecutionThread
。看github.com/Zer0Mem0ry/ntoskrnl/blob/master/Ex/delay.c以上是关于64位精度睡眠功能?的主要内容,如果未能解决你的问题,请参考以下文章