在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

Answers:


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
他们为什么不赞成使用简单的功能来处理复杂的功能。最好不要暂时使用usleep,而不是在nanosecond()上费劲。

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=c89,我建议使用struct timeval tv; tv.tv_sec = milliseconds / 1000; tv.tv_usec = milliseconds % 1000 * 1000; select(0, NULL, NULL, NULL, &tv);代替usleep(milliseconds * 1000);。信誉在这里
乔什·桑福德

好答案!注意,这里是nanosleep()文档:man7.org/linux/man-pages/man2/nanosleep.2.html。为此处使用的每个特定于平台的功能发布文档链接将很有用。
加布里埃尔·斯台普斯

另请注意,gcc -Wall -g3 -std=c11 -o sleep_test sleep_test.c && ./sleep_test在Linux Ubuntu(gcc版本4.8.4)上进行编译时,会收到以下警告:warning: implicit declaration of function ‘usleep’ [-Wimplicit-function-declaration]。解决方案是在代码的最顶部添加以下2个定义: 1)#define __USE_POSIX199309和2)#define _POSIX_C_SOURCE 199309L两者都需要使代码在没有任何警告的情况下进行编译(并使用nanoseconds()其具有的功能)。
加布里埃尔·斯台普斯

相关答案我​​刚刚做了:stackoverflow.com/a/55860234/4561887
Gabriel Staples

32

或者到usleep(),在2008年POSIX没有定义(虽然它确定了到2004年POSIX,这显然是可用于Linux和其他平台符合POSIX标准的历史),在2008年POSIX标准定义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
“没有sigalarm的风险”:哪种风险和哪种情况?打电话入睡吗?
马西莫'18

2
@Massimo,有关usleep的链接规范,其中有几句话涉及未指定的SIGALARM行为。(基本上,可以通过旧的警报机制实现usleepsleep的运行,您可以想象这会使usleep和SIGALARM的安全使用变得复杂。我不知道有任何现代系统可以这样做,但是仍然规格)
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

示例不会睡几秒钟,而且与仅使用usleep()之类的东西相比,这不是一个好的解决方案。
维克多·奥坎波
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.