如何在C中暂停非整数时间

  • 本文关键字:整数 时间 暂停 c linux
  • 更新时间 :
  • 英文 :


我正在编写一个简单的程序,当我将一个非整数值传递给sleep()函数时,它会给我一个错误。有没有其他函数,或者使用sleep()的不同方法,可以让我暂时暂停程序不到一秒钟(或者,比如2.5)?

mario.c:34:13:错误:函数"usleep"的隐式声明在C99中无效[-Werror,-Wimplicit函数声明]
usleep(30000)
^

usleep将暂停特定数量的微秒。例如:

usleep(500000);

将暂停半秒钟。

在某些系统上,根据编译器配置等,在包含unistd.h(理想情况下,在源文件的开头)之前,您可能需要定义_GNU_SOURCE,并使用:

#define _GNU_SOURCE

POSIX.1-2001标准定义了函数nanosleep(),它非常适合于此。与sleep()usleep()不同,nanosleep()不干扰信号。

然而,当前的Linux C库倾向于将usleep()实现为nanosleep()的包装器。如果strace是一个测试程序(比如运行strace /bin/sleep 1),您可以看到这一点。

但是,由于nanosleep()是POSIX.1-2001标准的一部分,因此绝对推荐使用。

例如:

#define _POSIX_C_SOURCE 200112L
#include <time.h>
#include <errno.h>
/* Sleep; returns un-slept (leftover) time.
*/
double dsleep(const double seconds)
{
    const long  sec = (long)seconds;
    const long  nsec = (long)((seconds - (double)sec) * 1e9);
    struct timespec  req, rem;
    if (sec < 0L)
        return 0.0;
    if (sec == 0L && nsec <= 0L)
        return 0.0;
    req.tv_sec = sec;
    if (nsec <= 0L)
        req.tv_nsec = 0L;
    else
    if (nsec <= 999999999L)
        req.tv_nsec = nsec;
    else
        req.tv_nsec = 999999999L;
    rem.tv_sec = 0;
    rem.tv_nsec = 0;
    if (nanosleep(&req, &rem) == -1) {
        if (errno == EINTR)
            return (double)rem.tv_sec + (double)rem.tv_nsec / 1000000000.0;
        else
            return seconds;
    } else
        return 0.0;
}

上面的大部分逻辑是确保(无论浮点舍入模式等)纳秒字段始终在[0999999999]内(包括[09999999999]),并确保用负值调用它是安全的(在这种情况下,它只返回零)。

如果你想以整数毫秒为单位指定持续时间,你可以使用

#define _POSIX_C_SOURCE 200112L
#include <time.h>
#include <errno.h>
/* Sleep; returns un-slept (leftover) time.
*/
long msleep(const long ms)
{
    struct timespec  req, rem;
    if (ms <= 0L)
        return 0L;
    req.tv_sec = ms / 1000L;
    req.tv_nsec = (ms % 1000L) * 1000000L;
    rem.tv_sec = 0;
    rem.tv_nsec = 0;
    if (nanosleep(&req, &rem) == -1) {
        if (errno == EINTR)
            return (long)rem.tv_sec * 1000L + rem.tv_nsec / 1000000L;
        else
            return ms;
    } else
        return 0L;
}

上面没有必要将rem清零,但通过这种方式编写,这两个函数非常健壮,即使偶尔会出现系统问题或库错误。

使用usleep的最初建议的明显问题是忽略了_GNU_SOURCE,这是一个几乎所有POSIX扩展都适用于Linux的建议。

这对我来说是在没有警告的情况下编译的,使用带有严格警告标志的c99

#include <unistd.h>
#include <time.h>
int main(void)
{             
    usleep(1);
    nanosleep(0,0);
    return 0;
}

和(从其他脚本中提取)

ACTUAL_GCC=c99 gcc-stricter -D_GNU_SOURCE -c foo.c
#!/bin/sh
OPTS="-O -Wall -Wmissing-prototypes -Wstrict-prototypes -Wshadow -Wconversion 
-W 
    -Wbad-function-cast 
    -Wcast-align 
    -Wcast-qual 
    -Wmissing-declarations 
    -Wnested-externs 
    -Wpointer-arith 
    -Wwrite-strings 
    -ansi 
    -pedantic 
 "
${ACTUAL_GCC:-gcc} $OPTS "$@"

如前所述,usleepnanosleep函数是扩展。更常见的是,使用selectpoll。这些函数用于等待一个或多个打开文件上的活动的指定时间间隔。作为一种特殊情况,select甚至不必等待文件,只需使用时间间隔。与nanosleep一样,select使用时间间隔结构来允许双精度值,但其值范围以微秒开始,而nanosleep以纳秒开始。

这些函数都是Linux C库的一部分。

ncurses(像任何X/Open curses一样)提供了一个等待毫秒的函数napms。在内部,ncurses使用(自1998年以来)nanosleepusleep,这取决于它们的可用性(毕竟它们是扩展),或者使用selectpoll的内部函数,这也取决于可用性。

使用此宏暂停非整数秒:

#include "unistd.h"
#define mysleep(s) usleep(s*1000000)

sleep()的int值表示以毫秒为单位的暂停时间,而不是秒。所以,要暂停一秒钟,你可以把它传给1000。在2.5秒内,你会超过2500。在半秒内,你会超过500。

这将允许您将延迟指定为以秒为单位的浮点值
该功能一直执行到启动和停止之间的差值大于请求的延迟。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void floatdelay ( float delay);
int main()
{
    float pause = 1.2;
    floatdelay ( pause);
    return 0;
}
void floatdelay ( float delay)
{
    clock_t start;
    clock_t stop;
    start = clock();
    stop = clock();
    while ( ( (float)( stop - start)/ CLOCKS_PER_SEC) < delay) {
        stop = clock();
    }
}

最新更新