实现繁忙循环的最佳方法是什么?如果我错了,请纠正我?
while (1); // obviously eats CPU.
while (1) { sleep(100); } // Not sure if it is the correct way ?
答案 0 :(得分:7)
要进行无限等待,对于信号(还有什么),有pause()
系统调用。你必须把它放在一个循环中,因为每次传递信号时它都会返回(总是带-1并且errno设置为EINTR):
while (1)
pause();
作为一个奇怪的说明,这就是AFAIK记录到总是失败的唯一POSIX功能。
更新:感谢dmckee,在下面的评论中,sigsuspend()
也始终失败。它与pause()
完全相同,但它更符合信号。不同之处在于它具有参数,因此除了EFAULT
之外,它还会失败EINTR
。
答案 1 :(得分:3)
繁忙的循环是永远不会阻塞并持续检查某些条件的循环。小睡眠足以避免100%的CPU使用率 实现忙等待的最佳方法是不实现它。而不是它,你可以使用阻塞调用或回调。
答案 2 :(得分:2)
Linux已经有了(POSIX 1.g) pselect 一段时间了。如果您正在使用信号处理程序或用户定义的信号,我认为这值得研究。它还解决了其他方法中出现的一些微妙的竞争条件。
我知道你提到了'忙碌循环',但我认为'阻塞循环'是你所追求的。
答案 3 :(得分:0)
如何防止数据依赖关系对其进行优化
首先,当然,只有在您有充分的理由不使用非忙碌循环时才应使用忙碌循环,非忙碌循环通常更有效,请参见:https://codereview.stackexchange.com/questions/42506/using-a-for-loop-or-sleeping-to-wait-for-short-intervals-of-time
现在,如果您只写以下内容,则仅关注繁忙的循环:
while (1);
或:
for (unsigned i = 0; i < 100; i++);
然后可以按照Are compilers allowed to eliminate infinite loops?
所述对这两个参数进行优化由于这个原因,正如在How to prevent GCC from optimizing out a busy wait loop?中详细解释的那样,我将它们写为:
while (1) asm("");
或:
for (unsigned i = 0; i < 100; i++) {
__asm__ __volatile__ ("" : "+g" (i) : :);
}