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 NtDelayExecutionPLARGE_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位精度睡眠功能?的主要内容,如果未能解决你的问题,请参考以下文章

将 64 位整数加载到双精度 SSE2 寄存器的最佳方法?

有没有办法在 msp430 中进行多精度算术(整数大于 64 位)?

double精确到几位小数

单精度与双精度

单精度、双精度各有几位小数?

单精度和双精度有啥不同?