2

当你有一个紧密的循环轮询某事物的状态时,我不太确定如何进行轮询而不妨碍其他想要使用 CPU 的进程。例如,这样做:

while (state == BUSY) state = check_state();

好像很浪费资源。我认为最好的方法是:

while (state == BUSY) {
    sched_yield();
    state = check_state();
}

我希望 top 会将进程列为睡眠状态,即使它在执行此操作时确实消耗了 100% 的 CPU。这样,该过程将(我希望)“很好地”轮询。但事实并非如此。目前我有

while (state == BUSY) {
    sleep(1);
    state = check_state();
}

这是完全可以接受的,但我觉得它可以做得比这更好。有这样做的标准做法吗?

4

5 回答 5

3

不要在 sched_yield() 上旋转,它会严重破坏调度程序的优先级检测,即使从性能角度来看它的互操作性很好,也会破坏电池寿命和功耗指标。如果您的应用程序可以容忍延迟,那么使用超时轮询(即使是像 10Hz 这样的短时间)是非常可取的,如果仍然不理想的话。

正确的答案取决于 check_state() 实际需要做什么。您是否绝对确定您不能安排事情以使您的状态更改是您可以阻止的内核可见事件?

于 2009-10-07T18:49:01.670 回答
1

不幸的是,没有良心民意调查这样的事情。轮询始终是反应时间和资源消耗之间的权衡:轮询周期越短,反应时间越好,但资源消耗越高。轮询周期越长,您节省的能源就越多,但您的应用程序的反应性就越低。

投票总是丑陋的,不管你怎么看。如果您试图以正确的方式做事,则必须使用更好的机制,即通知。这意味着您的 check_state() API 是一个糟糕的 API,因为它只允许您轮询状态;您需要一个旨在在状态更改时通知您的功能。通常,这样的函数会在状态发生变化时使某些 fd 可读,因此您可以同步或异步等待 fd 上的事件,并且仅在此类事件发生时才唤醒。

于 2011-06-23T11:21:59.480 回答
1

我不认为这是您可以使用pollepoll的东西?

于 2009-10-07T18:59:36.763 回答
0

我认为您可以使用libeventlibev

两者都提供了处理此类事情的设施。

于 2009-10-07T19:04:04.620 回答
0

在我的实时工作中,我通常会选择一个合理的超时时间(比如 10us),然后根据条件和 RDTSC(时间戳计数器)进行旋转。

如果您想长时间旋转(例如超过 10 毫秒),我建议您在其中放置一个小的睡眠语句,以便其他东西有机会运行。

于 2009-10-07T19:25:56.167 回答