检测系统在循环中暂停

2024-06-09 11:15:50 发布

您现在位置:Python中文网/ 问答频道 /正文

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

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

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

对于这种情况有什么常用的方法吗?最好是操作系统独立请,我不想钩到操作系统的事件和诸如此类。你知道吗


Tags: 方法算法trueif系统事件情况now
2条回答

首先,polling is inferiour to notifications因为它浪费了系统资源,而这些资源本来可以用来做有用的工作(而您当前的循环也是busy loop)。当然,电源管理事件系统是特定于操作系统的(请参见Power Management Notifications in Linuxhow to hook to events / messages in windows using python),但是如果您正在编写一个系统监视器应用程序,您无论如何也无法隐藏操作系统的差异。你知道吗


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

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

注意you will get false positives if your process gets preempted by others。这也是为什么使用系统通知是一种非常优越的方式的另一个原因。你知道吗

我认为这个算法有效:

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

这将在while循环中的任何行之后立即检测到挂起:

  • 在第一行之后挂起将被第二行检测到(因为last1将是旧的)。你知道吗
  • 第四行将检测到第二行之后挂起(因为last1将是旧的)。你知道吗
  • 第4行将检测到第3行之后的挂起(因为last1和last2都是旧的)。你知道吗
  • 第2行将检测到第4行之后的挂起(因为最后2行是旧的)。你知道吗

我相信这是检测系统挂起所需的最少代码量。如果我错了,请纠正我。你知道吗

相关问题 更多 >