相关文章推荐
寂寞的松树  ·  Docker-compose redis ...·  2 年前    · 
沉着的水龙头  ·  初学C#类 - 简书·  2 年前    · 
风流的墨镜  ·  2亿数据量PostgreSQL ...·  2 年前    · 
踢足球的伤痕  ·  c# - ...·  2 年前    · 

无休止的While循环会占用CPU资源吗?

27 人关注

根据我的理解,你写的Linux Daemon在一个无尽的循环中听一个请求。
Something like..

int main() {
    while(1) {
        //do something...

ref: http://www.thegeekstuff.com/2012/02/c-daemon-process/

我读到过,睡眠程序会使它进入等待模式,这样它就不会占用资源。

1.如果我想让我的守护神每隔1秒检查一次请求,下面的内容会不会很耗资源?

int main() {
    while(1) {
        if (request) {
            //do something...
        sleep(1)

2.如果我去掉睡眠,是否意味着CPU的消耗将上升100%?

3.有没有可能在不消耗资源的情况下运行一个无尽的循环?比如......如果它什么都不做,只是自己循环。或者只是sleep(1)。

无尽的循环和CPU资源对我来说是个谜。

2 个评论
睡眠告诉调度器,让其他进程在特定的时间内代替你的进程在CPU上运行(太简单了)。你的程序在休眠时不会消耗任何CPU资源。即使只是睡眠几毫秒,也能使事情像你展示的那样在无尽的循环中顺利进行。
如果你是 listening 那么你应该使用一些多路复用的系统调用,如 poll(2) (或更老的、几乎过时的 select(2) )。
c++
c
linux
infinite-loop
daemon
resting
resting
发布于 2012-12-03
3 个回答
Eric Postpischil
Eric Postpischil
发布于 2012-12-03
已采纳
0 人赞同

poll select 的调用(由Basile Starynkevitch在评论中提到)或semaphore(由Als在回答中提到)是等待请求的正确方式,这取决于情况。在没有 poll select 的操作系统上,应该有类似的东西。

替换代码4】、 YieldProcessor sched_yield 都不是合适的方法,原因如下。

替换代码5】和 sched_yield 只是将进程移到了可运行队列的末尾,但仍保持可运行状态。其效果是,它们允许其他具有相同或更高优先级的进程执行,但是,当这些进程完成后(或者如果没有),那么调用 YieldProcessor sched_yield 的进程继续运行。这导致了两个问题。一个是低优先级的进程仍然不会运行。另一个问题是,这导致处理器一直在运行,消耗能源。我们更希望操作系统能够识别出什么时候没有进程需要运行,并使处理器进入低功率状态。

替换代码4】可能允许这种低功耗状态,但它在猜测距离下一个请求到来还有多长时间,它在没有必要的情况下反复唤醒处理器,而且它使进程对请求的响应度降低,因为即使有请求需要服务,进程也会继续睡眠直到请求时间到期。

替换代码0】和 select 调用正是为这种情况设计的。它们告诉操作系统,这个进程想为它的一个I/O通道上的请求提供服务,但除此之外没有任何工作要做。这允许操作系统将该进程标记为不可运行,并在合适的情况下将处理器置于低功率状态。

使用semaphore可以提供同样的行为,只是唤醒进程的信号来自于另一个进程提高semaphore,而不是I/O通道中产生的活动。当做一些工作的信号以这种方式到达时,semaphores是合适的;只要使用 poll 或semaphore中的哪一个更适合你的情况。

poll select 或信号灯导致内核模式调用的批评是不相关的,因为其他方法也会导致内核模式的调用。一个进程不能自己睡觉,它必须调用操作系统来请求睡觉。同样, YieldProcessor sched_yield 也向操作系统发出请求。

Alok Save
Alok Save
发布于 2012-12-03
0 人赞同

有没有可能在不消耗资源的情况下运行一个无尽的循环?比如......如果它什么都不做,只是自己循环。或者只是sleep(1)。

有一个更好的选择。
你可以只用一个 旗语 , which remains blocked at the begining of loop and you can signal the 旗语 whenever you want the loop to execute.
请注意,这不会占用任何资源。

"不会吃任何资源 "并不完全正确......创建semaphore需要使用内核资源和对象,是一个相当重的操作。等待信号是一个内核模式的操作,并且会产生一个上下文切换到内核模式。
如果使用了超时,那么semaphore是合适的,但是sleep可能仍然是最好的。 如果你想让你的代码在以下情况下触发,那么semaphore是最相关的 either timeout or 某种外部事件。
谢谢你提到semaphore。有时间的话,我得去探索一下:)
Kevin A. Naudé
Kevin A. Naudé
发布于 2012-12-03
0 人赞同

简短的回答是肯定的--取消睡眠可以得到100%的CPU--但答案确实取决于一些额外的细节。 它消耗所有能得到的CPU,除非...

  • The loop body is trivial, and optimised away.
  • The loop contains a blocking operation (like a file or network operation). The link you provide suggests to avoid this, but it is often a good idea to block until something relevant happens.
  • EDIT : 对于你的情况,我支持@Als提出的建议。

    EDIT 2: 我估计这个答案得到了-1,因为我声称阻断操作实际上可以是一个好主意。 [如果你是-1,你应该在评论中留下一个动机,这样我们都可以学到一些东西。]

    目前流行的想法是,非阻塞(基于事件)的IO是好的,阻塞是坏的。 这种观点过于简单,因为它假定所有执行IO的软件都可以通过使用非阻塞操作来提高吞吐量。

    什么? 我真的是在说,使用非阻塞式IO实际上可以减少吞吐量吗? 是的,它可以。 当一个进程服务于一个单一的活动时,使用阻塞式IO实际上是更好的,因为阻塞式IO只燃烧那些在进程存在时已经支付的资源。