C 到毫秒之间是否有替代的睡眠功能?

Is there an alternative sleep function in C to milliseconds?

提问人:ant2009 提问时间:7/21/2009 最后编辑:Jonathan Lefflerant2009 更新时间:2/8/2021 访问量:451124

问:

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

源代码包含头文件,程序员使用该函数等待一段时间的毫秒。这在 Linux 上不起作用。<windows.h>Sleep()

但是,我可以使用该函数,但它使用以秒为单位的整数。我不想将毫秒转换为秒。有没有替代的睡眠函数可以与 Linux 上的 gcc 编译一起使用?sleep(seconds)

C Linux 睡眠

评论

0赞 EsmaeelE 11/26/2017
sleep(/*seconds*/)在作品中,但如果我使用 with without ,它就不起作用。<unistd.h>printf("some things")\n
1赞 EsmaeelE 11/26/2017
在这种情况下,我们必须在fflush(stdout);printf()

答:

278赞 caf 7/21/2009 #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 */
};

使用 实现的示例函数,如果睡眠被信号中断,则继续睡眠: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;
}

评论

75赞 6/6/2019
为什么他们一直弃用简单函数来换取复杂函数。与其在纳秒()上绞尽脑汁,不如暂时使用usleep。
1赞 Anton Krug 8/27/2020
USLEEP 不能做纳秒,而 nanosleep 应该
5赞 Erich Kitzmueller 12/28/2020
@AntonKrug 在许多环境中,即使是微秒级精度也无法实现。
2赞 Anton Krug 12/29/2020
@ErichKitzmueller嵌入式和裸机环境可以达到~50ns。这取决于 HAL 和库是如何实现的。例如,您可以在甚至没有文件系统的目标上调用 fopen(将字符输出到 UART)。并在没有屏幕的设备上调用 printf。然而,代码通常在 x86 主机和嵌入式目标之间完全可移植。
28赞 pilcrow 7/21/2009 #2

除了 usleep 之外,带有 NULL 文件描述符集的不起眼的选择将让您以微秒级精度暂停,并且没有并发症的风险。SIGALRM

Sigtimedwait 和 SigWaitInfo 提供类似的行为。

评论

1赞 Massimo 3/22/2018
“没有 SIGALARM 的风险”:哪种风险和哪种情况?称 sleep 和 usleep ?
3赞 pilcrow 11/14/2018
@Massimo,usleep 的链接规范中有几句关于未指定的 SIGALARM 行为的句子。(基本上,usleepsleep 可以通过旧的警报机制实现,您可以想象这会使 usleep 和 SIGALARM 的安全使用变得复杂。我不知道有任何现代系统以这种方式做到这一点,但它仍然在规范中。
16赞 Anonymous 7/21/2009 #3
#include <unistd.h>

int usleep(useconds_t useconds); //pass in microseconds
33赞 Jonathan Leffler 7/21/2009 #4

与 POSIX 2008 中未定义的 usleep() 不同(尽管它在 POSIX 2004 之前被定义,并且显然可以在 Linux 和其他具有 POSIX 合规性历史的平台上使用),POSIX 2008 标准定义了 nanosleep():

nanosleep- 高分辨率睡眠

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

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

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

76赞 Bernardo Ramos 3/3/2015 #5

您可以使用此跨平台功能:

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

评论

3赞 Josh Sanford 9/30/2016
当我们没有 时,例如 或 ,我建议使用 代替 。信用在这里_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);
1赞 Gabriel Staples 4/26/2019
很好的答案!请注意,这是文档:man7.org/linux/man-pages/man2/nanosleep.2.html。发布此处使用的每个特定于平台的功能的文档链接将很有用。nanosleep()
0赞 Gabriel Staples 4/26/2019
另请注意,在 Linux Ubuntu 上使用 gcc 版本 4.8.4 进行编译时,我收到以下警告: .解决方案是将以下 2 个定义添加到代码的最顶部:1) 和 2) 。两者都需要让代码在没有任何警告的情况下进行编译(并且还要使用它可用的函数)。gcc -Wall -g3 -std=c11 -o sleep_test sleep_test.c && ./sleep_testwarning: implicit declaration of function ‘usleep’ [-Wimplicit-function-declaration]#define __USE_POSIX199309#define _POSIX_C_SOURCE 199309Lnanoseconds()
0赞 Gabriel Staples 4/26/2019
我刚才的相关回答:stackoverflow.com/a/55860234/4561887
0赞 Philippe Carphin 7/19/2023
就我在 Linux 上而言,开始时未定义,因此被包括在内。包含要定义到上面的东西的原因。因此,在内部,版本由预处理器选择,这会导致未包含编译错误。如果我在顶部添加,则会导致为第一个块定义它。 是一个随机选择,可能定义 。_POSIX_C_SOURCEunistd.hunistd.h_POSIX_C_SOURCE199309Lvoid sleep_ms()nanosleeptime.h#include <stdlib.h>stdlib.h_POSIX_C_SOURCE