문제

전통적인 임베디드 프로그래밍에서는 다음과 같은 지연 기능을 제공합니다.

for(i=0;i<255;i++)
   for(j=0;j<255;j++);

마이크로프로세서의 관점에서 이것이 sleep() 함수가 작동하는 방식입니까?

C에 sleep() 함수에 대한 대안이 있습니까?

도움이 되었습니까?

해결책

대안은 당신이 무엇을하려고하는지, 어떤 OS에 있는지에 달려 있습니다.

시간을 낭비하고 싶다면 다음과 같은 도움이 될 수 있습니다.

대부분의 UNIX- 타입 시스템에서는 '수면'기능이 있습니다. 일반적으로 한 마이크로 초만 잠을 잘 수 없기 때문에 조심하십시오.

일부 UNIX- 타입 시스템에서, 선택 시스템 호출은 상당히 정확한 서브 초위 대기를하기 위해 모든 파일 디스크립터 세트와 함께 사용할 수 있습니다.

Windows Systems에서는 수면이 거의 있지만 거의 동일하지만 여러 밀리 초를 섭취합니다.

멀티 태스킹 운영 체제에서 수면 기능은 때때로 매개 변수로 0을 제공 할 수 있습니다. 이로 인해 일반적으로 기능이 타임 슬라이스를 포기하게하지만 다른 작업이 실행되지 않으면 즉시 다시 예약됩니다.

다른 팁

당신이 설명하는 루프의 종류를 "바쁜 대기"라고합니다. 실제 운영 체제에서 수면은 바쁜 대기를 유발하지 않습니다. 수면 기간이 끝날 때까지 운영 체제에 프로세스를 예약하지 않도록 지시합니다.

일반적인 메커니즘 중 하나는 사용하는 것입니다 select() 이는 타임 아웃을 보장하고 수면 시간을 시간 초과로 지정합니다.

// Sleep for 1.5 sec
struct timeval tv;
tv.tv_sec = 1;
tv.tv_usec = 500000;
select(0, NULL, NULL, NULL, &tv);

그만큼 select() 일반적으로 파일 설명자 세트를 확인하고 최소한 하나가 I/O를 수행 할 준비가 될 때까지 기다립니다. 준비되지 않은 경우 (또는이 경우 FD가 지정되지 않은 경우) 시간이 걸립니다.

의 이점 select() 바쁜 루프를 통해 수면 중에 자원이 거의 소비되는 반면, 바쁜 루프는 우선 순위 수준에 의해 허용되는만큼 프로세서를 독점한다는 것입니다.

게시 한 코드를 사용하여 임베디드 시스템에서 잠을 자지 않습니다. 괜찮은 컴파일러는 완전히 제거 할 수 있으며 컴파일러가 제거되지 않더라도 프로세서를 타이트한 루프로 실행하면 전원을 태우기 때문에 내장 시스템의 문제입니다. 전력 사용량이 낮기 때문에 전력 사용에 대해 배터리 관리를 실행하지 않는 시스템조차도 전원 사용량이 저렴하기 때문에 전원 공급 장치와 냉각을 의미합니다.

일반적 으로이 작업을 수행하는 방식은 CPU가 일종의 유휴 또는 수면 지침을 구현하여 일시적으로 처리 명령을 중지하게됩니다. 타이머 회로에 연결된 외부 인터럽트 라인은 프로세서를 정기적으로 다시 깨우고 CPU는 오랫동안 잠 들어 있는지 확인하기 위해 CPU 검사를 가리키며 다시 잠들지 않으면 다시 잠들게됩니다.

//Pseudo code
int start = getTime();
int end = start + sleepTime;

while (getTime() < end) {
       asm("SLEEP");
}

정확한 세부 사항은 프로세서마다 다릅니다. OS에서 프로세스로 실행중인 경우 수면 호출은 일반적으로 스케줄러에게 프로세스를 중단하라고 지시 한 다음 커널은 다른 프로세스를 예약 할 것인지 CPU를 수면할지 여부를 결정합니다. 또한, 위의 코드는 마감일 보증 등을 원하는 실시간 시스템에 적합하지 않습니다. 그러한 경우 루프에서 시간을 가져와야하는 경우 시간 인터럽트 기간을 알아야합니다. 마감일을 날리고 타이머 하드웨어 또는 바쁜 대기를 잠재적으로 프로그래밍 할 수 있습니다.

OP에서 "임베디드 프로그래밍"에 대해 이야기합니다. 임베디드 작업을하고 있고 Sleep ()와 같은 것이 필요한 경우 종종 하드웨어 카운터/타이머가 있습니다. 이것은 아키텍처마다 다르므로 데이터 시트를 살펴보십시오.

임베디드 작업을하지 않는다면 사과드립니다 :)

For-Loops를 사용하는 경우, 그들이 무엇을 컴파일하는지, 그리고 그 지침이 주어진 클럭 속도에서 얼마나 오래 걸리는지 더 잘 알 수 있습니다. 그리고 CPU가 지침을 실행하고 다른 것이 없는지 확인하십시오 (이는 임베디드 시스템에서 수행 할 수 있지만 인터럽트를 분해하기 때문에 까다 롭습니다).

그렇지 않으면 실제로 얼마나 오래 걸릴지 알 수 없습니다.

초기 PC 게임은이 문제가있었습니다. 그들은 4.7MHz PC를 위해 제작되었으며, 더 빠른 컴퓨터가 등장했을 때, 그들은 플레이 할 수 없었습니다.

'수면'이 작동 할 수있는 가장 좋은 방법은 CPU가 주어진 시점에있는 시간을 알 수있는 것입니다. 반드시 실제 시간 (7:15 AM)은 아니지만 적어도 상대 시간 (어느 시점 이후 8612 초).

이렇게하면 현재 시간에 델타를 적용하고 현재+델타에 도달 할 때까지 루프에서 기다릴 수 있습니다.

CPU주기에 의존하는 것은 CPU가 다른 작업으로 나가서 루프를 매달릴 수 있으므로 본질적으로 신뢰할 수 없습니다.

CPU가 1 초에 증가하는 메모리 매핑 된 16 비트 I/O 포트가 있다고 가정 해 봅시다. ints도 16 비트 인 내장 시스템의 메모리 위치 0x33에 있다고 가정 해 봅시다. 수면이라는 기능은 다음과 같습니다.

void sleep (unsigned int delay) {
    unsigned int target = peek(0x33) + delay;
    while (peek(0x33) != target);
}

Peek ()가 매번 메모리 내용을 반환해야하므로 (컴파일러를 최적화하는 컴파일러를 최적화하지 않기 때문에, 귀하의 Wehen Statement는 초당 두 번 이상 실행되므로 대상을 놓치지 않도록합니다. 내가 제시하고있는 개념에 영향을 미치지 않는 운영 문제입니다.

sleep() 작동 방식에 대한 추가 정보가 있습니다. 여기

그런데 바쁜 대기는 아마추어에게 꼭 필요한 것은 아니지만 다른 목적으로 사용하고 싶은 프로세서를 태울 수도 있습니다.시간 소스를 사용하는 경우 해당 소스의 세분성으로 제한됩니다.예를 들어1ms 타이머가 있고 500uS를 원한다면 문제가 있는 것입니다.임베디드 시스템이 500uSec 동안 루프에서 윙윙거린다는 사실을 처리할 수 있다면 이는 허용될 수 있습니다.그리고 원하는 세분성을 가진 타이머가 있더라도 적절한 시간에 해당 타이머에서 인터럽트를 해제해야 합니다. 그런 다음 인터럽트 핸들러를 디스패치하고... 코드로 이동해야 합니다.때로는 바쁜 루프가 가장 편리한 솔루션입니다. 때때로.

바쁜 기다리는 것은 임베디드 시스템에서도 아마추어를위한 것입니다. 실시간 소스를 사용하십시오.

괜찮은 C 컴파일러는 추가 작업없이 코드를 완전히 제거하면 지연이 사라집니다.

수면은 실제로 수면 과정이 스케줄링 큐 외부에 배치되는 운영 체제와 인터페이스합니다. 나는 보통 사용합니다 :

poll(0, 0, milliseconds);

POSIX 호환 시스템의 경우. select 또한 Windows에서도 작동합니다 (아마도 Native API가 있어야합니다 (아마도 호출됩니다. Sleep) 그에 대한.)

조셉 알바 하리 (Joseph Albahari)의 'C#'의 'Threading'에서 20 페이지는 이것에 대한 흥미로운 토론을 가지고 있습니다. .NET에서는 1ms 미만으로 잠을 잘 수는 없지만 DateTime.ticks는 100 나노 초 (= 0.1 마이크로 초) 간격입니다. 5 축 CNC 스테퍼를 제어하기 위해 스텝 명령 사이에 10 마이크로 초만 일시 중지하면됩니다. 나는 Micro Controller를 사용하여 불쾌한 루핑을 수행했지만 어쨌든 전체 무리가 있으면 작업에 대한 프로세서를 넘겨주는 것이 좋습니다. 가능한 경우 스레드를 중지하십시오. 적어도 항상 같은 것은 아닙니다.

#include <Windows.h>

static NTSTATUS(__stdcall *NtDelayExecution)(BOOL Alertable, PLARGE_INTEGER DelayInterval) = (NTSTATUS(__stdcall*)(BOOL, PLARGE_INTEGER)) GetProcAddress(GetModuleHandle("ntdll.dll"), "NtDelayExecution");

static NTSTATUS(__stdcall *ZwSetTimerResolution)(IN ULONG RequestedResolution, IN BOOLEAN Set, OUT PULONG ActualResolution) = (NTSTATUS(__stdcall*)(ULONG, BOOLEAN, PULONG)) GetProcAddress(GetModuleHandle("ntdll.dll"), "ZwSetTimerResolution");




static void SleepShort(float milliseconds) {
    static bool once = true;
    if (once) {
        ULONG actualResolution;
        ZwSetTimerResolution(1, true, &actualResolution);
        once = false;
    }

    LARGE_INTEGER interval;
    interval.QuadPart = -1 * (int)(milliseconds * 10000.0f);
    NtDelayExecution(false, &interval);
}

예, 문서화되지 않은 일부 커널 기능을 사용하지만 솔직히 말해서 대부분의 제안보다 훨씬 빠르고 잘 작동합니다 (예를 들어 CPU의 양으로 제한됩니다. 예를 들어 광산은 500 나노초 만 잠을 잘 수 있습니다 (0.5)).

Linux Usleep (int microseconds) Nanosleep (...) 더 정확한 인수에 대한 인수를 참조하십시오.

Unix- 파생 OS에서는 신호 () 호출을 예약 할 수 있으며 신호가 올릴 때까지 코드가 단순히 코드를 차단합니다. 신호는 목적을위한 것이며 매우 간단하고 효율적입니다.

시도 ...이 문제를 실제로 해결하려는 시도, 즉 작동하는 일 (위의 답변의 시도와는 다르지 않음) LOL

나는 여전히이 코드를 개선하기 위해이 코드를 개선해야합니다. 애드온은 거의 없습니다.

// Sleep for both Windows and Linux: 
// Too bad? No one proposed you a solution that works? 
// Since Windows has no select.h nor poll.h, an implementation
// is necessary.
//  
// Solutions on boards are often refered to use either select or poll, but ok, what about C (not c++)?
//
/// implementation of poll is destined in this attempt for windows
/// Ideally, you add this part of code to the header of you *.c file, and it might work through...

#ifdef WIN32
#include <time.h>
#include <sys/time.h>
#include <ws2tcpip.h>
#include <Winsock2.h>
#include <windows.h>
/* winsock doesn't feature poll(), so there is a version implemented
 * in terms of select() in mingw.c. The following definitions
 * are copied from linux man pages. A poll() macro is defined to
 * call the version in mingw.c.
 */
#define POLLIN      0x0001    /* There is data to read */
#define POLLPRI     0x0002    /* There is urgent data to read */
#define POLLOUT     0x0004    /* Writing now will not block */
#define POLLERR     0x0008    /* Error condition */
#define POLLHUP     0x0010    /* Hung up */
#define POLLNVAL    0x0020    /* Invalid request: fd not open */
struct pollfd {
  SOCKET fd;        /* file descriptor */
  short events;     /* requested events */
  short revents;    /* returned events */
};

int mingw_poll (struct pollfd *, unsigned int, int);

#define poll(x, y, z)        mingw_poll(x, y, z)
#endif





int mingw_poll(struct pollfd *fds, unsigned int nfds, int timo)
{
    struct timeval timeout, *toptr;
    fd_set ifds, ofds, efds, *ip, *op;
    int i, rc;

    /* Set up the file-descriptor sets in ifds, ofds and efds. */
    FD_ZERO(&ifds);
    FD_ZERO(&ofds);
    FD_ZERO(&efds);
    for (i = 0, op = ip = 0; i < nfds; ++i) {
    fds[i].revents = 0;
    if(fds[i].events & (POLLIN|POLLPRI)) {
        ip = &ifds;
        FD_SET(fds[i].fd, ip);
    }
    if(fds[i].events & POLLOUT) {
        op = &ofds;
        FD_SET(fds[i].fd, op);
    }
    FD_SET(fds[i].fd, &efds);
    } 

    /* Set up the timeval structure for the timeout parameter */
    if(timo < 0) {
    toptr = 0;
    } else {
    toptr = &timeout;
    timeout.tv_sec = timo / 1000;
    timeout.tv_usec = (timo - timeout.tv_sec * 1000) * 1000;
    }

#ifdef DEBUG_POLL
    printf("Entering select() sec=%ld usec=%ld ip=%lx op=%lx\n",
           (long)timeout.tv_sec, (long)timeout.tv_usec, (long)ip, (long)op);
#endif
    rc = select(0, ip, op, &efds, toptr);
#ifdef DEBUG_POLL
    printf("Exiting select rc=%d\n", rc);
#endif

    if(rc <= 0)
    return rc;

    if(rc > 0) {
        for (i = 0; i < nfds; ++i) {
            int fd = fds[i].fd;
        if(fds[i].events & (POLLIN|POLLPRI) && FD_ISSET(fd, &ifds))
            fds[i].revents |= POLLIN;
        if(fds[i].events & POLLOUT && FD_ISSET(fd, &ofds))
            fds[i].revents |= POLLOUT;
        if(FD_ISSET(fd, &efds))
            /* Some error was detected ... should be some way to know. */
            fds[i].revents |= POLLHUP;
#ifdef DEBUG_POLL
        printf("%d %d %d revent = %x\n", 
                FD_ISSET(fd, &ifds), FD_ISSET(fd, &ofds), FD_ISSET(fd, &efds), 
                fds[i].revents
        );
#endif
        }
    }
    return rc;
}

이 게시물에서 기능을 찾았습니다 (http://cboard.cprogramming.com/c-programming/111229-how-use-sleep-function.html) 그리고 그것은 작동합니다 :

#include <stdio.h>
#include <windows.h>

int main()
{
    puts("Hello \n");
    /* in windows.h is declared the Sleep (upper S) function and it takes time in 
miliseconds */
    Sleep(3000);
    puts("World \n");
    return 0;
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top