C에서 밀리 초로 대체 슬립 기능이 있습니까?


133

Windows에서 컴파일 된 소스 코드가 있습니다. Red Hat Linux에서 실행되도록 변환하고 있습니다.

소스 코드에는 <windows.h>헤더 파일 이 포함되어 있으며 프로그래머는이 Sleep()함수를 사용하여 밀리 초 동안 기다렸습니다. Linux에서는 작동하지 않습니다.

그러나 sleep(seconds)함수를 사용할 수 는 있지만 초 단위의 정수를 사용합니다. 밀리 초를 초로 변환하고 싶지 않습니다. Linux에서 gcc 컴파일과 함께 사용할 수있는 대체 절전 기능이 있습니까?


sleep(/*seconds*/)<unistd.h>내가 함께 사용하는 경우 작동하지만 printf("some things")없는 \n, 그하지 작동합니다.
EsmaeelE

이 경우에 사용하려면 fflush(stdout);매번 출력을 플러시해야합니다 printf()
EsmaeelE

답변:


179

예-이전 POSIX 표준이 정의 usleep()되었으므로 Linux에서 사용할 수 있습니다.

   int usleep(useconds_t usec);

기술

usleep () 함수는 (적어도) usec 마이크로 초 동안 호출 스레드의 실행을 일시 중단합니다. 시스템 활동이나 호출 처리에 소요 된 시간 또는 시스템 타이머 단위로 인해 절전 시간이 약간 길어질 수 있습니다.

usleep()마이크로 초가 걸리므 로 밀리 초 단위로 절전 모드로 전환하려면 입력에 1000을 곱해야합니다.


usleep()이후 더 이상 사용되지 않으며 POSIX에서 제거되었습니다. 새 코드의 경우 nanosleep()선호됩니다.

   #include <time.h>

   int nanosleep(const struct timespec *req, struct timespec *rem);

기술

nanosleep()최소한 지정된 시간 *req이 경과하거나 호출 스레드에서 핸들러 호출을 트리거하거나 프로세스를 종료하는 신호 전달이 완료 될 때까지 호출 스레드 실행을 일시 중단합니다 .

구조 timespec은 나노초 정밀도로 시간 간격을 지정하는 데 사용됩니다. 다음과 같이 정의됩니다.

       struct timespec {
           time_t tv_sec;        /* seconds */
           long   tv_nsec;       /* nanoseconds */
       };

신호로 중단 된 경우 절전 모드를 계속 msleep()사용하여 구현 된 예제 함수 nanosleep():

#include <time.h>
#include <errno.h>    

/* msleep(): Sleep for the requested number of milliseconds. */
int msleep(long msec)
{
    struct timespec ts;
    int res;

    if (msec < 0)
    {
        errno = EINVAL;
        return -1;
    }

    ts.tv_sec = msec / 1000;
    ts.tv_nsec = (msec % 1000) * 1000000;

    do {
        res = nanosleep(&ts, &ts);
    } while (res && errno == EINTR);

    return res;
}

19
복잡한 함수에 대해 단순한 함수를 계속 사용하지 않는 이유는 무엇입니까? nanosecond ()에서 뇌를 파열시키는 대신 당분간 usleep을 사용할 수도 있습니다.

52

이 크로스 플랫폼 기능을 사용할 수 있습니다 :

#ifdef WIN32
#include <windows.h>
#elif _POSIX_C_SOURCE >= 199309L
#include <time.h>   // for nanosleep
#else
#include <unistd.h> // for usleep
#endif

void sleep_ms(int milliseconds) // cross-platform sleep function
{
#ifdef WIN32
    Sleep(milliseconds);
#elif _POSIX_C_SOURCE >= 199309L
    struct timespec ts;
    ts.tv_sec = milliseconds / 1000;
    ts.tv_nsec = (milliseconds % 1000) * 1000000;
    nanosleep(&ts, NULL);
#else
    usleep(milliseconds * 1000);
#endif
}

3
또는 _POSIX_C_SOURCE >= 199309L의 경우와 같이 가없는 경우 대신을 사용 하는 것이 좋습니다 . 신용은 여기에 간다 . -ansi-std=c89struct timeval tv; tv.tv_sec = milliseconds / 1000; tv.tv_usec = milliseconds % 1000 * 1000; select(0, NULL, NULL, NULL, &tv);usleep(milliseconds * 1000);
Josh Sanford

좋은 답변입니다! 참고, 여기입니다 nanosleep(): 문서 man7.org/linux/man-pages/man2/nanosleep.2.html . 여기에 사용 된 각 플랫폼 별 기능에 대한 설명서 링크를 게시하면 유용합니다.
가브리엘 스테이플

또한 gcc -Wall -g3 -std=c11 -o sleep_test sleep_test.c && ./sleep_testgcc 버전 4.8.4를 사용 하여 Linux Ubuntu에서 컴파일 할 때 다음 경고가 표시 warning: implicit declaration of function ‘usleep’ [-Wimplicit-function-declaration]됩니다. 해결책은 코드의 맨 위에 다음 2 개의 정의추가하는 것입니다 : 1) #define __USE_POSIX199309및 2) #define _POSIX_C_SOURCE 199309L. 코드 모두 경고없이 코드를 컴파일 nanoseconds()하고 사용 가능한 함수를 사용하도록해야 합니다.
가브리엘 스테이플


32

다른 방법에 usleep()(이 POSIX 2004 년까지 정의하지만, 그것은 POSIX 준수의 역사를 가진 리눅스와 다른 플랫폼에서 분명히 볼 수 있습니다) POSIX 2008 년에 정의되지 않은, POSIX의 2008 표준을 정의 nanosleep():

nanosleep -고해상도 수면

#include <time.h>
int nanosleep(const struct timespec *rqtp, struct timespec *rmtp);

nanosleep()함수는 rqtp인수에 의해 지정된 시간 간격 이 경과하거나 신호가 호출하는 스레드로 전달 될 때까지 현재 스레드가 실행을 중지 하도록하며, 그 동작은 신호 포착 기능을 호출하거나 프로세스를 종료하는 것입니다. 인수 값이 휴면 해상도의 정수 배로 올림되거나 시스템에 의한 다른 활동의 스케줄링으로 인해 일시 중단 시간이 요청 된 시간보다 길 수 있습니다. 단, 신호에 의해 중단되는 경우를 제외하고, 정지 시간 rqtp은 시스템 시계 CLOCK_REALTIME에 의해 측정 된대로에 지정된 시간보다 작아서는 안된다.

nanosleep()기능을 사용해도 신호의 작동 또는 차단에는 영향을 미치지 않습니다.


24

usleep 외에도 NULL 파일 디스크립터 세트가 있는 겸손한 선택을 사용하면 마이크로 초 정밀도로 일시 중지하고 SIGALRM합병증 의 위험이 없습니다 .

sigtimedwait 및 sigwaitinfo 는 유사한 동작을 제공합니다.


1
'시갈 암의 위험없이': 어떤 위험과 어떤 경우? 수면과 수면을 호출?
Massimo

2
@Massimo에 대한 연결 사양 usleep은 지정되지 않은 SIGALARM 행동에 여러 문장이있다. (기본적으로 usleepsleep 은 기존 알람 메커니즘을 통해 구현할 수 있습니다.이 알람 메커니즘은 usleep 및 SIGALARM 의 안전한 사용법을 복잡하게 만들 수 있다고 상상할 수 있습니다 . spec.)
pilcrow


-7
#include <stdio.h>
#include <stdlib.h>
int main () {

puts("Program Will Sleep For 2 Seconds");

system("sleep 2");      // works for linux systems


return 0;
}

1
이것은 밀리 초 동안 잠들지 않으며 훨씬 더 많은 오버 헤드를 발생시켜 타이밍을 더욱 신뢰할 수 없게 만듭니다.
Devolus

1
예는 마이크로 초 동안 잠을 자지 않으며 usleep ()과 같은 것을 사용하는 것과 비교할 때 해결책이 아닙니다.
Victor Ocampo
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.