【问题标题】:Is there an alternative sleep function in C to milliseconds?C 到毫秒是否有替代睡眠功能?
【发布时间】:2010-11-12 12:49:34
【问题描述】:

我有一些在 Windows 上编译的源代码。我正在将其转换为在 Red Hat Linux 上运行。

源代码已包含<windows.h> 头文件,程序员已使用Sleep() 函数等待一段时间。这不适用于 Linux。

但是,我可以使用sleep(seconds) 函数,但它使用以秒为单位的整数。我不想将毫秒转换为秒。我可以在 Linux 上使用 gcc 编译的替代睡眠功能吗?

【问题讨论】:

  • sleep(/*seconds*/) in <unistd.h> 有效,但如果我与printf("some things") 一起使用而没有\n,则它不起作用。
  • 为了在这种情况下使用,我们必须在每个printf() 之后用fflush(stdout); 刷新输出

标签: c linux sleep


【解决方案1】:

是的 - 较早的 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 */
};

使用nanosleep()实现的示例msleep()函数,如果被信号中断则继续睡眠:

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

【讨论】:

  • 为什么他们不断弃用简单的函数来代替复杂的函数。与其在 nanosecond() 上绞尽脑汁,还不如暂时使用 usleep。
  • usleep 不能做纳秒,而 nanosleep 应该
  • @AntonKrug 在许多环境中,即使是微秒级的精度也无法实现。
  • @ErichKitzmueller 嵌入式和裸机环境可以达到约 50ns。这取决于 HAL 和库是如何实现的。例如,您可以在甚至没有文件系统的目标上调用 fopen(将字符输出到 UART)。并在没有屏幕的设备上调用 printf。然而,代码通常可以在 x86 主机和嵌入式目标之间完全移植。
【解决方案2】:

你可以使用这个跨平台功能:

#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
    if (milliseconds >= 1000)
      sleep(milliseconds / 1000);
    usleep((milliseconds % 1000) * 1000);
#endif
}

【讨论】:

  • 当我们没有_POSIX_C_SOURCE &gt;= 199309L 时,例如-ansi-std=c89,我建议使用struct timeval tv; tv.tv_sec = milliseconds / 1000; tv.tv_usec = milliseconds % 1000 * 1000; select(0, NULL, NULL, NULL, &amp;tv); 而不是usleep(milliseconds * 1000);。信用去here
  • 很好的答案!请注意,这是nanosleep() 文档:man7.org/linux/man-pages/man2/nanosleep.2.html。发布此处使用的每个特定于平台的功能的文档链接会很有用。
  • 另请注意,在 Linux Ubuntu 上使用 gcc -Wall -g3 -std=c11 -o sleep_test sleep_test.c &amp;&amp; ./sleep_test 编译时,使用 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
【解决方案3】:
#include <stdio.h>
#include <stdlib.h>
int main () {

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

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


return 0;
}

【讨论】:

  • 这不会休眠几毫秒,还会引入更多开销,这使得计时更加不可靠。
  • 示例不会休眠几微秒,而且与仅使用类似 usleep() 的方法相比,这并不是一个好的解决方案。
【解决方案4】:

作为usleep() 的替代品,在 POSIX 2008 中没有定义(尽管它是在 POSIX 2004 之前定义的,并且它显然在 Linux 和其他具有 POSIX 合规性历史的平台上可用),POSIX 2008 标准定义了 @ 987654322@:

nanosleep - 高分辨率睡眠

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

nanosleep() 函数将导致当前线程暂停执行,直到经过rqtp 参数指定的时间间隔或将信号传递给调用线程,并且它的动作是调用信号-catch 函数或终止进程。暂停时间可能比请求的时间长,因为参数值被四舍五入到睡眠分辨率的整数倍,或者因为系统调度了其他活动。但是,除了被信号中断的情况外,挂起时间不得小于rqtp指定的时间,以系统时钟CLOCK_REALTIME测量。

nanosleep()函数的使用对任何信号的动作或阻塞都没有影响。

【讨论】:

    【解决方案5】:
    #include <unistd.h>
    
    int usleep(useconds_t useconds); //pass in microseconds
    

    【讨论】:

      【解决方案6】:

      除了 usleep,带有 NULL 文件描述符集的不起眼的 select 可以让您以微秒级的精度暂停,而不会出现 SIGALRM 并发症的风险。

      sigtimedwait and sigwaitinfo 提供类似的行为。

      【讨论】:

      • '没有 sigalarm 的风险':哪种风险和哪种情况?调用 sleep 和 usleep ?
      • @Massimo,usleep 的链接规范有几句话关于未指定的 SIGALARM 行为。 (基本上,usleepsleep 允许通过旧的 alarm 机制实现,您可以想象这会使 的安全使用复杂化usleep 和 SIGALARM。我不知道有任何现代系统可以这样做,但它仍在规范中。)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-11-30
      • 1970-01-01
      • 1970-01-01
      • 2010-11-19
      • 2015-11-19
      • 1970-01-01
      • 2018-02-17
      相关资源
      最近更新 更多