while(1)的用途; C中的陈述
while(1);
目的是什么? 服务? 我知道while(1)
(无分号)无限循环,类似于螺旋locking的情况。 但是我不知道while(1);
可用于 ?
示例代码
if(!condition) { while(1); }
注意:这不是do
– while()
或plain while(1)
。
请注意,所有语言的有效声明不一定是有用的。 它们根据语言的语法是有效的。 可以build立许多类似的“无用的”陈述,如if (1);
。 我看到这样的陈述是有条件的( if
, while
等)和空的陈述的结合;
(这也是一个有效的陈述,虽然它显然没有特定的目的)。
这就是说,我遇到while (1);
在安全代码。 当用户使用embedded式设备做了一些非常糟糕的事情时,阻止他们尝试其他任何东西可能是件好事。 while (1);
,我们可以无条件地阻止设备,直到经过authentication的操作员手动重新启动设备。
while(1);
也可以是内核恐慌执行的一部分,虽然for(;;) {}
循环似乎是expression无限循环的更常见的方式,并且可能有一个非空的体(例如panic_blink()
)。
如果您深入到汇编(从embedded式系统的angular度来看,这更容易理解,或者如果您尝试对引导加载程序进行编程)
你会意识到while循环只是一个jmp指令
(pseudo code: starting loop address) add ax, bx add ax, cx cmp ax, dx jz (pseudo code: another address location) jmp (pseudo code: starting loop address)
让我们解释这是如何工作的,处理器将继续执行指令顺序…无论如何。 所以进入这个循环的时候,它会把寄存器bx添加到ax并存储在ax中,将ax添加到寄存器cx并存储到ax,cmp ax,dx(这意味着从ax减去dx)jz指令意味着跳转到另一个地址位置)如果设置了零标志(如果上述减法的结果为0,那么标志寄存器中的位将被设置),然后将jmp设置为开始循环地址(非常简单),然后重做整个过程。
我在这个大会上打扰你的原因是告诉你,这会在C中转化为
int A,B,C,D; // initialize to what ever; while(true) { A = A + B; A = A + C; if((AD)==0) {break;} } // if((XY)==0){break;} is the // cmp ax, dx // jz (pseudo code: another address location)
所以想象一下,在汇编中的senario如果你只是有一个非常长的指令列表,并没有结束一个jmp(while循环)重复一些部分或加载一个新的程序或做一些事情…最终处理器将达到最后一条指令,然后加载下面的指令来找不到任何东西(它会冻结或三重故障或什么)。
这就是为什么当你希望程序在触发事件之前什么都不做的时候,你必须使用一个while(1)循环,这样处理器就不停地跳到原来的位置,而不能到达那个空的指令地址。 当事件被触发时,它跳转到事件处理程序指令地址,执行它,清除中断并返回到while(1)循环,只是在等待进一步中断的位置跳转。 顺便说一句,如果你想了解更多关于while(1)的内容,可以称之为超循环(superloop)…只是对于那些疯狂地想要在这一点上争辩和否定评论的人来说,这不是一个汇编教程或者讲座或者任何东西。 这只是简单的英语解释,尽可能简单,忽略了许多底层的细节,如指针和堆栈,以及在某些情况下简化的东西,以获得一个点。 没有人在这里查找文档的准确性,我知道这个C代码不会像这样编译,但是这只是为了演示!
这被标记为C,但我将从C ++透视图开始。 在C ++ 11中,编译器可以自由地优化while(1);
远。
从C ++ 11草案标准n3092,第6.5节第5段(重点是我的):
一个循环,在for语句的for-init语句之外,
– 不会调用库I / O函数
– 不访问或修改易失性对象
– 不执行同步操作(1.10)或primefaces操作(第29章)
可能由执行方式假定终止。 [ 注:这是为了允许编译器转换,例如删除空循环,即使无法证实终止。 – 结束注意]
C11标准有一个类似的条目,但有一个关键的区别。 从C11草案标准n1570(重点是我的):
一个迭代语句, 其控制expression式不是一个常量expression式 , 不执行input/输出操作,不访问易失性对象,在其主体中不执行同步或primefaces操作,控制expression式或(在for声明)其expression式-3 ,可以由实现来承担终止。 157)
156)一个省略的控制expression式被一个非零常量(常量expression式)替代。
这是为了允许编译器转换,例如,即使在无法certificate终止的情况下,也可以清除空循环。
这意味着while(1);
可以假定在C ++ 11中终止,但不在C11中终止。 即使如此,注意157(不是绑定)被某些供应商解释为允许他们删除那个空的循环。 while(1);
在C ++ 11和C11中是定义的还是未定义的行为。 因为循环是空的,所以可以在C ++ 11中删除。 在C11中, while(1);
是可certificate的不终止,这是不明确的行为。 由于程序员调用了UB,因此编译器可以自由地执行任何操作,包括删除有问题的循环。
while(1);
关于优化编译器的删除while(1);
有一些关于stackoverflow的讨论while(1);
。 例如, 编译器是否允许消除无限循环? , 一个空的for循环用作睡眠优化了吗? , 优化一个“while(1);” 在C ++ 0x 。 请注意,前两个是C特定的。
我假设while(1);
不与do
循环关联…
while(1);
的唯一半有用的实现while(1);
我所看到的是一个等待中断的无所事事的循环; 例如等待SIGCHLD的父进程,表示subprocess已经终止。 在所有subprocess终止之后,父进程的SIGCHLD处理程序可以终止父线程。
它诀窍,但浪费了大量的CPU时间。 这样的用法也许应该执行某种睡眠来周期性地放弃处理器。
embedded式软件的用法是使用看门狗来实现软件重置:
while (1);
或者相当但更安全,因为它使意图更清楚:
do { /* nothing, let's the dog bite */ } while (1);
如果看门狗启用并且在x毫秒后没有被确认,我们知道它会重置处理器,所以用它来实现软件重置。
一个我曾经看过的地方while(1);
是embedded式编程。
该架构使用主线程来监视事件和工作线程来处理它们。 有一个硬件看门狗定时器( 在这里解释),将在一段时间后执行模块的软复位。 在主线程轮询循环内,它将重置该计时器。 如果主线程检测到不可恢复的错误, while(1);
将被用来捆绑主线程,从而触发看门狗复位。 我相信主张失败是有一段while(1);
以及。
正如其他人所说,这只是一个无限循环,什么都不做,完全类似于
while (1) { /* Do nothing */ }
用分号循环确实有一个主体。 当作为一个语句使用时,一个分号是一个空语句 ,循环体是由这个空语句组成的。
为了便于阅读,为了让读者明白null语句是循环的主体,我build议把它写在一个单独的行上:
while (1) ;
否则,在“while”行的末尾很容易忽略,通常不会有分号,读者可能会把下一行误认为是循环的主体。
或者使用空的复合语句。
while(1);
其实很有用。 特别是当它是一个有某种密码的程序时,你想禁止用户使用该程序,例如,他input了3次错误的密码。 用while(1);
会停止程序的进度,直到程序重新启动后才会发生任何事情,主要是出于安全原因。
这可能被用来等待中断 。 基本上,你初始化所有你需要的东西,并开始等待一些事情发生。 之后,一些特定的function被调用并执行,然后返回到等待状态。
可以按下button,鼠标点击/移动,收到数据等。
更重要的是, 类似的东西通常被UI框架所使用。 它等待有关用户操作的信号。
在AVR芯片组编程中(使用C语言编程语言)这个语句经常用到,它起着事件循环的作用。
假设我想devise一个计数器,所以我可以使用这个代码来实现它:
void interrupt0() { /* check if key pressed, count up the counter */ } void main() { /* Common inits */ /* Enable interrupt capability and register its routine */ /* Event loop */ while(1); }
既然情况总是如此,我们可以说我们正在使用math中已知的逻辑重言式。 虽然循环certificate永远是真的,但不会停止循环,除非被代码强制或资源崩溃。
我认为, while(1);
被使用是因为在代码的早些时候在这个线程上设置了一个EventHandler或中断。 当你知道你的代码只能“等待”很短的时间时,使用标准的线程安全locking代码可能会相当昂贵(及时)。 因此,您可以使用while(1);
来设置中断和“旋转” while(1);
其中,尽pipe是一个忙等待(不让CPU空闲/服务其他线程)占用很less的周期来build立。
总之,当你的线程等待中断或事件时,这是一个'廉价'的自旋锁。