Windows 无睡眠的CPU空闲循环
我现在正在学习WIN32 ASM,我想知道是否有像“空闲”无限循环这样的东西根本不消耗任何资源。基本上,我需要一个运行过程来进行试验,如下所示:Windows 无睡眠的CPU空闲循环,windows,assembly,Windows,Assembly,我现在正在学习WIN32 ASM,我想知道是否有像“空闲”无限循环这样的东西根本不消耗任何资源。基本上,我需要一个运行过程来进行试验,如下所示: loop: ; alternative to sleep... jmp loop 是否存在使进程空闲的情况?是的,有些体系结构支持固有的空闲状态AKAhalt 例如,在x86中,操作码0xf4。可能只能在特权模式下调用 我发现的Linux用户空间示例: 你不能两全其美。您可以使用CPU,也可以让它做其他事情。使用rep;否(也称为暂停),
loop:
; alternative to sleep...
jmp loop
是否存在使进程空闲的情况?是的,有些体系结构支持固有的空闲状态AKA
halt
例如,在x86中,操作码0xf4
。可能只能在特权模式下调用
我发现的Linux用户空间示例:
你不能两全其美。您可以使用CPU,也可以让它做其他事情。使用
rep;否代码>(也称为暂停
),正如弗拉德·拉扎连科所建议的那样。但是,如果您循环而不将核心交给另一个进程,那么至少该虚拟核心不能做任何其他事情。您所说的“消耗资源”是什么意思
如果你只是想要一个什么都不做的命令?如果是这样的话,nop
就可以做到这一点,你可以想循环多少就循环多少:rep;没有。然而,CPU实际上会忙于工作:执行“无操作”指令
如果您想要一条指令导致CPU本身停止,那么您可能有点运气不佳:虽然有办法做到这一点,但您不能从用户空间执行。注意:您不应该使用空循环使应用程序处于空闲状态。它会将您的处理器加载到100%
当Win32环境中没有GUI活动时,有几种方法可以使应用程序空闲。main(记录在MSDN中)在主循环中使用“GetMessage”函数,以便从消息队列中提取消息。
当消息队列为空时,此函数将空闲,占用非常少的处理器时间,等待消息到达消息队列
下面是使用FASM宏库的示例:
msg_loop:
invoke GetMessage, msg, NULL, 0, 0
cmp eax, 1
jb end_loop
jne msg_loop
invoke TranslateMessage, msg
invoke DispatchMessage, msg
jmp msg_loop
当您希望捕捉应用程序进入空闲状态的时刻并进行一些低优先级的一次性处理(例如,根据应用程序的状态启用/禁用工具栏上的按钮)时,可以使用另一种方法
在这种情况下,必须使用PeekMessage和WaitMessage的组合。即使消息队列为空,PeekMessage函数也会立即返回。通过这种方式,您可以检测到这种情况并提供一些要完成的空闲任务,然后您必须调用WaitMessage以使进程空闲等待传入消息
下面是我的代码中的一个简化示例(使用FreshLib宏):
使用环0访问级别(如内核驱动程序),您可以使用x86 HLT操作码,但您需要具备系统编程技能才能真正理解如何使用它。以这种方式使用HLT需要启用中断(不屏蔽)并保证中断发生(例如系统计时器),因为中断返回将执行HLT之后的下一条指令
如果没有环0访问,您将永远找不到任何x86操作码来进入“空闲”模式。。。
您只能找到一些功耗较低的指令(无内存访问、无缓存访问、无FPU访问、ALU使用率较低……。rep如何;没有sleep()
,sched_yield()
等是要求操作系统执行其他操作的系统调用。您可以在汇编程序中进行这些调用。但这些并不是真正意义上的CPU什么都不做的指令,而是更高级的指令。TerminateProcess()是停止执行指令的好方法。写无限循环不是,也没有明显的用处。HLT指令只能由特权代码使用。我不想问明显的问题,但是。。。从你对答案的评论来看,睡眠不正是你想要的吗?你想要核心做其他事情,或者完全闲置一段时间,然后你想要控制回来。这就是睡眠的作用。你为什么要找一个替代品?问题是什么?这不是汇编语言的好用途。当您认为自己可以比编译器做得更好时,您可以使用汇编语言,通常是试图使某些东西运行得更快。当你的目标是什么都不做时,就不需要速度了。@BenjaminWeiss:那么答案是否定的。你想让操作系统安排另一个线程在CPU上运行,如果一个线程已经准备好运行,或者只有当操作系统没有其他工作可以让该内核做时,才让该内核暂时休眠。这显然需要调用操作系统,因为只有操作系统调度器知道该内核在任何特定时间可以执行哪些其他工作,并且只有操作系统可以安排中断以将内核从睡眠中唤醒。这就是Sleep
的具体功能。操作系统会允许吗?也就是说,需要什么样的保护级别?需要中断或类似的方式来唤醒它。它对用户进程没有用处。可以从处理器的内核模式读取hlt。所以你需要一个系统调用。我试过了,但它仍然占用了我整个CPU的25%。(25%是因为我有一个四核?!)@BenjaminWeiss:除了运行你的代码,你还想让这个核做其他的事情吗?还是不?没有第三种选择。如果该内核正在运行您的代码,那么它就不能做任何其他事情。因此,使用了四个内核中的一个,25%。我希望进程消耗几乎0%的CPU。WINAPI调用Sleep暂停进程(甚至可能暂停当前正在运行的线程)。“我想要一个替代方案。”本杰明维斯:我不明白。睡眠正是你想要的。另一种选择将是低劣的,或者充其量也不会更糟。你为什么想要一个替代方案?消耗资源我实际上是指CPU百分比的最低成本。@BenjaminWeiss:那么你希望核心能够做其他事情?然后,您必须调用操作系统,让它在该CPU上安排另一个线程。呼叫请注意,使用率仍将至少为25%——如果核心可以做其他事情,那么它将处于
msg_loop:
invoke GetMessage, msg, NULL, 0, 0
cmp eax, 1
jb end_loop
jne msg_loop
invoke TranslateMessage, msg
invoke DispatchMessage, msg
jmp msg_loop
; Main message loop
Run:
invoke PeekMessageA, msg, 0, 0, 0, PM_REMOVE
test eax,eax
jz .empty
cmp [msg.message], WM_QUIT
je .terminate
invoke TranslateMessage, msg
invoke DispatchMessageA, msg
jmp Run
.empty:
call OnIdle
invoke WaitMessage
jmp Run
.terminate:
FinalizeAll
stdcall TerminateAll, 0