首页 > 解决方案 > 检测系统在循环中挂起

问题描述

我正在尝试使用以下算法检测系统挂起:

while True:
    lastchecked = now()
    if now() - lastchecked > 1s: print "suspend detected!"

但是我遇到了一个问题:如果挂起发生在第 2 行和第 3 行之间,那么循环会捕获它。但是如果挂起发生在第一行和第二行之间,那么算法就会失败。

这种情况有一些常用的方法吗?最好是独立于操作系统的,我不想挂钩操作系统事件等。

标签: pythonalgorithm

解决方案


首先,轮询不如通知,因为它浪费了系统资源,而这些资源可以花在有用的工作上(而且您当前的循环也是一个繁忙的循环)。自然,电源管理事件系统是特定于操作系统的(请参阅Linux 中的电源管理通知以及如何使用 python 连接到 Windows 中的事件/消息),但是如果您正在编写系统监视器应用程序,则无论如何您都无法隐藏操作系统差异.


现在,这里的关键是在内存中始终有两个时间戳并覆盖旧的:

T1
  \
   T2
   <- compare
  / 
T3
 <- compare
  \
   T4
   etc
  /

然后,无论何时发生挂起,下一个时间戳都将设置得比它应该设置的晚,并且比较会看到差异。

这样,您甚至不需要每秒钟左右轮询一次!您的轮询间隔只需与您想要检测的最短暂停时间一样短。例如,如果您想检测至少 30 秒的暂停时间,您只需每 30 秒轮询一次:如果系统睡眠时间更长,则可以保证“错过一个节拍”。

i=0
poll_period=30
t=[time.time()]*2
while True:
    # actually, poll period will be slightly longer due to code overhead:
    # https://stackoverflow.com/questions/26774186/looping-at-a-constant-rate-with-high-precision-for-signal-sampling
    # but that doesn't make a difference in this case
    time.sleep(poll_period)
    t[i]=time.time()
    if t[i] - t[(i+1)%2] > poll_period + 2: print "suspend detected"
    i = (i+1)%2

请注意,如果您的进程被其他人抢占,您将得到误报。这就是为什么使用系统通知是一种非常优越的方式的另一个原因。


推荐阅读