我正在编写一个简单的程序,当我将一个非整数值传递给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 "$@"
如前所述,usleep
和nanosleep
函数是扩展。更常见的是,使用select
或poll
。这些函数用于等待一个或多个打开文件上的活动的指定时间间隔。作为一种特殊情况,select
甚至不必等待文件,只需使用时间间隔。与nanosleep
一样,select
使用时间间隔结构来允许双精度值,但其值范围以微秒开始,而nanosleep
以纳秒开始。
这些函数都是Linux C库的一部分。
ncurses(像任何X/Open curses一样)提供了一个等待毫秒的函数napms
。在内部,ncurses使用(自1998年以来)nanosleep
或usleep
,这取决于它们的可用性(毕竟它们是扩展),或者使用select
或poll
的内部函数,这也取决于可用性。
使用此宏暂停非整数秒:
#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();
}
}