Development Tip

while (1)의 목적;

yourdevel 2021. 1. 9. 10:59
반응형

while (1)의 목적; C의 성명


어떤 목적이 while(1);있습니까? 나는 while(1)(세미콜론 없음) 무한 루프를 알고 있으며 스핀 록 상황과 유사합니다. 그러나 어디에서 while(1);사용할 수 있는지 모르겠습니다 .

샘플 코드

if(!condition)
{ 
  while(1);
}

참고 : 이것은 do- while()또는 평범한 경우가 아닙니다 while(1).


노트는 언어의 유효한 모든 진술은하지 마십시오 것을 해야 목적을 제공합니다. 그들은 언어의 문법에 따라 유효합니다. .NET과 같은 유사한 "쓸모없는"문장을 많이 작성할 수 있습니다 if (1);. 조건문 ( if, while등)과 빈 문 ;(명백하게 특정 목적을 제공하지는 않지만 유효한 문임 ) 의 결합으로 이러한 문이 표시됩니다 .

즉, while (1);보안 코드에서 만났습니다 . 사용자가 임베디드 장치로 매우 나쁜 일을 할 때 다른 작업을 시도하지 못하도록 차단하는 것이 좋습니다. 를 사용하면 while (1);공인 된 운영자가 수동으로 재부팅 할 때까지 장치를 무조건 차단할 수 있습니다.

while(1);for(;;) {}루프가 무한 루프를 표현하는 더 일반적인 방법 인 것처럼 보이지만 비어 있지 않은 본문 (예 :)이있을 수 있지만 커널 패닉 구현의 일부일 수도 있습니다 panic_blink().


어셈블리에 대해 자세히 살펴보면 (임베디드 시스템 관점에서 또는 부트 로더를 프로그래밍하려고했을 때 이해하기가 더 쉽습니다)

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에 저장하고, 레지스터 cx를 ax에 추가하고 ax, cmp ax, dx에 저장합니다 (이는 ax에서 dx를 빼는 것을 의미합니다). 위치) 제로 플래그가 설정되면 (위의 뺄셈 결과가 0이면 설정 될 플래그 레지스터의 비트) jmp를 시작 루프 주소 (매우 간단하게)로 설정하고 전체를 다시 실행합니다.

제가이 모든 어셈블리로 여러분을 괴롭혔던 이유는 이것이 C에서

int A,B,C,D;
// initialize to what ever;

while(true)
{
A = A + B;
A = A + C;

if((A-D)==0)
{break;}

}

// if((X-Y)==0){break;} is the 
// cmp ax, dx
// jz  (pseudo code: another address location)

So imagine the senario in assembly if you just had a very long list of instructions that didn't end with a jmp (the while loop) to repeat some section or load a new program or do something ... Eventually the processor will reach the last instruction and then load the following instruction to find nothing (it will then freeze or triple fault or something).

That is exactly why, when you want the program to do nothing until an event is triggered, you have to use a while(1) loop, so that the processor keeps jumping in its place and not reach that empty instruction address. When the event is triggered, it jumps to the event handler instructions address, executes it, clears the interrupt and goes back to your while(1) loop just jumping in its place awaiting further interrupts. Btw the while(1) is called a superloop if you want to read more about it ... Just for whoever that is insanely itching to argue and comment negatively at this point, this is not an assembly tutorial or a lecture or anything. It's just plain English explanation that is as simple as possible, overlooking a lot of underlying details like pointers and stacks and whatnot and at some instance over simplifying things to get a point across. No one is looking for documentation accuracy over here and I know this C code won't compile like this, but this is only for Demo !!


This is tagged C, but I'll start with a C++ perspective. In C++11, the compiler is free to optimize while(1); away.

From the C++11 draft standard n3092, section 6.5 paragraph 5 (emphasis mine):

A loop that, outside of the for-init-statement in the case of a for statement,
— makes no calls to library I/O functions, and
— does not access or modify volatile objects, and
— performs no synchronization operations (1.10) or atomic operations (Clause 29)
may be assumed by the implementation to terminate. [Note: This is intended to allow compiler transformations, such as removal of empty loops, even when termination cannot be proven. — end note ]


The C11 standard has a similar entry, but with one key difference. From the C11 draft standard n1570, (emphasis mine):

An iteration statement whose controlling expression is not a constant expression,156) that performs no input/output operations, does not access volatile objects, and performs no synchronization or atomic operations in its body, controlling expression, or (in the case of a for statement) its expression-3, may be assumed by the implementation to terminate.157)
156) An omitted controlling expression is replaced by a nonzero constant, which is a constant expression.
157) This is intended to allow compiler transformations such as removal of empty loops even when termination cannot be proven.


This means while(1); can be assumed to terminate in C++11 but not in C11. Even with that, note 157 (not binding) is interpreted by some vendors as allowing them to remove that empty loop. The difference between while(1); in C++11 and C11 is that of defined versus undefined behavior. Because the loop is empty it can be deleted in C++11. In C11, while(1); is provably non-terminating, and that is undefined behavior. Since the programmer has invoked UB, the compiler is free to do anything, including deleting that offending loop.

There have been a number of stackoverflow discussions on optimizing compilers deleting while(1);. For example, Are compilers allowed to eliminate infinite loops?, Will an empty for loop used as a sleep be optimized away?, Optimizing away a "while(1);" in C++0x. Note that the first two were C-specific.


I assume that the while(1); is not associated with a do loop...

The only semi-useful implementation of while(1); I have seen is a do-nothing loop waiting for an interrupt; such as a parent process waiting for a SIGCHLD, indicating a child process has terminated. The parent's SIGCHLD handler, after all child processes have terminated, can terminate the parent thread.

It does the trick, but wastes a lot of CPU-time. Such a usage should perhaps perform some sort of sleep to relinquish the processor periodically.


An usage on embedded software is to implement a software reset using the watchdog:

while (1);

or equivalent but safer as it makes the intent more clear:

do { /* nothing, let's the dog bite */ } while (1);

If the watchdog is enabled and is not acknowledged after x milliseconds we know it will reset the processor so use this to implement a software reset.


One place that I have seen a while(1); is in embedded programming.

The architecture used a main thread to monitor events and worker threads to handle them. There was a hardware watchdog timer (explanation here) that would perform a soft reset of the module after a period of time. Within the main thread polling loop, it would reset this timer. If the main thread detected an unrecoverable error, a while(1); would be used to tie up the main thread, thus triggering the watchdog reset. I believe that assert failure was implemented with a while(1); as well.


As others have said, it's just an infinite loop that does nothing, completely analogous to

while (1) {
    /* Do nothing */
}

The loop with the semicolon does have a body. When used as a statement, a single semicolon is a null statement, and the loop body consists of that null statement.

For readability, to make it plain to the reader that the null statement is the body of the loop, I recommend writing it on a separate line:

while (1)
    ;

Otherwise it is easy to miss it at the end of the "while" line, where there usually isn't a semicolon, and the reader can mistake the next line as the body of the loop.

Or use an empty compound statement instead.


while(1);

is actually very useful. Especially when it's a program that has some sort of passcode or so and you want to disable the use of the program for the user because, for an example, he entered the wrong passcode for 3 times. Using a while(1); would stop the program's progress and nothing would happen until the program is rebooted, mostly for security reasons.


This may be used to wait for Interrupt. Basically you initialize all things you need and start waiting for some thing to occur. After that some specific function is called and executed, after that it goes back to waiting state.

That thing could be button pressed, mouse click/move, data received and etc.

What is more I would say, similar stuff is really often used by UI frameworks. While it waits for signals about user actions.


In AVR chipsets programming (using C programming language) this statement is frequently used, It plays a role like event loop.

Suppose I want to design a count-up counter, So I can use this code for implementing it:

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);
} 

Since the condition is always true, we can say that we are using a logic tautology as known in mathematics. While the loop proofs to be always true it won´t stop looping unless forced by the code or until resources have collapsed.


I think that the reason that while(1); is used is because earlier in the code an EventHandler or interrupt has been set on this thread. Using standard Thread Safe locking code can be fairly costly (in time) when you know that your code will only 'wait' for a very short amount of time. Therefore you can set up the interrupt and 'spin' using while(1); which, although is a Busy Wait (doesn't let the CPU Idle/service other threads) takes up very few cycles to set up.

In summary, it's a 'cheap' spinlock while your thread waits for an interrupt or Event.

ReferenceURL : https://stackoverflow.com/questions/24278724/purpose-of-while1-statement-in-c

반응형