【问题标题】:How to idle a C program如何使 C 程序空闲
【发布时间】:2020-09-08 23:05:07
【问题描述】:

我用 C 语言编写了一个 CPU 密集型程序以在 Windows 上运行。在主循环中,我检查键盘是否按下以允许您中断执行以暂停程序。这个想法是如果程序使计算机速度过慢,则将线程释放给其他进程。按下键盘后,我使用 fgets() 等待更多键盘输入,这允许您稍后重新启动程序。这确实很好地减少了任务管理器中显示的 CPU 使用率。但我想知道是否有更明确的方法可以告诉操作系统此进程暂时不需要任何关注,以便将空闲时的开销降至最低。

我的理解是操作系统会定期让进程运行,然后在一定时间后停止运行。然后它以同样的方式检查其余的进程,直到它再次回到这个进程。如果它有足够的时间,该过程将运行最大允许时间。否则,它将提前停止并将控制权返回给操作系统。因此,如果没有键盘输入,像 fgets 这样的函数必须立即返回控制权,这就是为什么进程以接近 0% 的 CPU 运行的原因。所以我想问我问题的另一种方式是如何在我自己的代码中故意将控制权返回给操作系统。

【问题讨论】:

  • 也许只是为你的线程设置了一个低优先级?
  • 一般来说,您应该将 CPU 密集型工作卸载到另一个线程(可能降低优先级),并在您的“主线程”中处理用户界面,(特别是如果主线程是处理 GUI)。您的工作线程可以轮询原子“暂停”布尔值(比 KB I/O 轮询快得多),如果设置,则等待事件或信号量同步,直到主线程重置“暂停”并发出同步信号。跨度>
  • 需要重复系统调用的解决方案既浪费又不必要,使用超时的解决方案更糟。在 CPU 密集型任务循环中,无需再做任何事情,只需测试一个原子布尔值以查看是否已设置。
  • 如果某个答案帮助您解决了问题,请考虑接受。

标签: c windows operating-system


【解决方案1】:

我的问题是如何在自己的代码中故意将控制权交还给操作系统

您可以使用Sleep(0)SwitchToThread()。两者都将控制权交还给操作系统,并可能导致调用线程放弃剩余的时间片,但问题在于细节。

睡眠(0)

如果没有其他具有匹配优先级的线程准备好运行,则调用立即返回。否则,线程放弃其剩余的时间片。

您可以使用SwitchToThreadSleep(1) 解决优先级问题。后者的缺点是线程无条件放弃自己的时间片,不管其他线程是否准备好运行。

SwitchToThread()

如果没有其他线程(无论其优先级如何)准备好在线程的当前处理器上运行,则调用立即返回。否则,线程最多放弃一个时间片的剩余时间片。

或者,您可以更改进程(SetPriorityClass()PROCESS_MODE_BACKGROUND_BEGIN)或线程(SetThreadPriority()THREAD_MODE_BACKGROUND_BEGIN)的优先级,以便操作系统可以为您处理更重要的进程/线程的优先级。在您的情况下,这样做会更合适。调度程序将响应突然的 CPU 需求,而无需您进行任何额外的工作。

【讨论】:

  • 另一个处理 UI 的线程会更有效。轮询原子布尔值非常快。不需要重复的系统调用来满足 OP 的需求。
  • 我们不知道是否涉及 UI。在任何情况下,都不需要重复的系统调用。空闲优先级确保应用程序只会使用准备好的 CPU 运行。不过,关于SleepSwitchToThread 的部分回答了这个问题。
  • 轮询 KB 是一个 UI,尽管它很简单。降低优先级当然是部分解决方案 - 如果不需要手动控制执行,可能所有 OP 都需要:)
  • 我的理解是,当前的解决方案只是处理更重要线程的调度被应用程序阻塞的情况的一种解决方法——我可能错了:)
【解决方案2】:

您几乎可以通过两种方式做到这一点。要么使用阻塞函数读取输入,例如fgets,要么使用非阻塞函数读取输入。在第二种情况下,您需要合并某种超时。某些功能会为您执行此操作,例如 select。否则,您需要定期休眠您的进程或线程。

实际上,系统正在使用中断来确定哪些进程关心特定事件。

【讨论】:

  • 不,这是糟糕的设计:(
猜你喜欢
  • 2020-09-03
  • 1970-01-01
  • 2010-10-25
  • 1970-01-01
  • 2012-06-22
  • 1970-01-01
  • 2011-02-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多