- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在编写一个简单的程序,它检查耗时是否超过 1 秒。我使用clock_gettime()获取开始时间,然后调用sleep(5),获取新时间并检查差异是否大于1;我睡了 5 秒,那么它应该大于 5,但我的程序打印了一个奇怪的结果。
这是代码:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
int main()
{
struct timespec tv1,tv3,expected;
struct timespec nano1;
tv1.tv_nsec = 0;
tv3.tv_nsec = 0;
expected.tv_nsec = 400000;
if(clock_gettime(CLOCK_MONOTONIC,&tv3) == -1){
perror(NULL);
}
sleep(5);
if(clock_gettime(CLOCK_MONOTONIC,&tv1) == -1){
perror(NULL);
}
long nsec = tv1.tv_nsec - tv3.tv_nsec;
if(nsec>expected.tv_nsec){
printf("nsec runned: %ld nsec timeout: %ld\n",nsec,expected.tv_nsec);
}
printf("elapsed nanoseconds: %ld\n",nsec);
if((nsec>expected.tv_nsec))
printf("expired timer\n");
else
printf("not expired timer\n");
exit(EXIT_SUCCESS);
}
我的程序的输出是:
“经过的纳秒:145130”和“未过期超时”
问题出在哪里?
最佳答案
struct timespec
中表示的时间有两个组成部分:
tv_sec
— 一个time_t
整数秒值。tv_nsec
— 纳秒数的 32 位整数,0..999,999,999您的计算没有考虑 tv_sec
之间的差异值(value)观。纳秒值之间的差异如您所说的那么大,这有点令人惊讶,但绝非不可能。要获得全部差异,您需要考虑 tv_sec
和 tv_nsec
组件。
sub_timespec()
您可以使用如下函数减去两个值(以获得差值):
enum { NS_PER_SECOND = 1000000000 };
void sub_timespec(struct timespec t1, struct timespec t2, struct timespec *td)
{
td->tv_nsec = t2.tv_nsec - t1.tv_nsec;
td->tv_sec = t2.tv_sec - t1.tv_sec;
if (td->tv_sec > 0 && td->tv_nsec < 0)
{
td->tv_nsec += NS_PER_SECOND;
td->tv_sec--;
}
else if (td->tv_sec < 0 && td->tv_nsec > 0)
{
td->tv_nsec -= NS_PER_SECOND;
td->tv_sec++;
}
}
fmt_timespec
您可以使用如下函数将其格式化为具有指定小数位数的浮点值:
int fmt_timespec(const struct timespec *value, int dp, char *buffer, size_t buflen)
{
assert(value != 0 && buffer != 0 && buflen != 0);
if (value == 0 || buffer == 0 || buflen == 0)
{
errno = EINVAL;
return -1;
}
assert(dp >= 0 && dp <= 9);
if (dp < 0 || dp > 9)
{
errno = EINVAL;
return -1;
}
if ((value->tv_sec > 0 && value->tv_nsec < 0) ||
(value->tv_sec < 0 && value->tv_nsec > 0))
{
/* Non-zero components of struct timespec must have same sign */
errno = EINVAL;
return -1;
}
int len;
if (dp == 0)
len = snprintf(buffer, buflen, "%ld", value->tv_sec);
else
{
long nsec = value->tv_nsec;
long secs = value->tv_sec;
const char *sign = (secs < 0 || (secs == 0 && nsec < 0)) ? "-" : "";
if (secs < 0)
secs = -secs;
if (nsec < 0)
nsec = -nsec;
for (int i = 0; i < 9 - dp; i++)
nsec /= 10;
len = snprintf(buffer, buflen, "%s%ld.%.*ld", sign, secs, dp, nsec);
}
if (len > 0 && (size_t)len < buflen)
return len;
errno = EINVAL;
return -1;
}
<小时/>
标题time_io.h
声明 struct timespec
的格式和扫描功能; time_math.h
header 声明了加法和减法函数struct timespec
值(value)观。拥有如此多的 header 可能对代码进行了过度划分。
#include "time_io.h"
#include "time_math.h"
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
enum { NS_PER_SECOND = 1000000000 };
int main(void)
{
struct timespec tv3;
if (clock_gettime(CLOCK_MONOTONIC, &tv3) == -1)
perror("clock_gettime()");
sleep(5);
struct timespec tv1;
if (clock_gettime(CLOCK_MONOTONIC, &tv1) == -1)
perror("clock_gettime()");
struct timespec td;
sub_timespec(tv3, tv1, &td);
int64_t ts_in_ns = td.tv_sec * NS_PER_SECOND + td.tv_nsec;
char buffer[32];
fmt_timespec(&td, 9, buffer, sizeof(buffer));
printf("Elapsed time: %s (%" PRId64 " nanoseconds)\n", buffer, ts_in_ns);
return 0;
}
运行示例:
Elapsed time: 5.005192000 (5005192000 nanoseconds)
在运行 macOS Sierra 10.12.6 的 Mac 上(最终有 clock_gettime()
- 早期版本的 Mac OS X 不支持它),分辨率为 clock_gettime()
是 1000 纳秒,实际上是微秒。因此,在 Mac 上最后 3 位小数始终为零。
add_timespec()
为了完整起见,您可以添加两个 struct timespec
值:
void add_timespec(struct timespec t1, struct timespec t2, struct timespec *td)
{
td->tv_nsec = t2.tv_nsec + t1.tv_nsec;
td->tv_sec = t2.tv_sec + t1.tv_sec;
if (td->tv_nsec >= NS_PER_SECOND)
{
td->tv_nsec -= NS_PER_SECOND;
td->tv_sec++;
}
else if (td->tv_nsec <= -NS_PER_SECOND)
{
td->tv_nsec += NS_PER_SECOND;
td->tv_sec--;
}
}
scn_timespec()
并且“扫描”过程更加困惑(输入通常比输出更困惑):
int scn_timespec(const char *str, struct timespec *value)
{
assert(str != 0 && value != 0);
if (str == 0 || value == 0)
{
errno = EINVAL;
return -1;
}
long sec;
long nsec = 0;
int sign = +1;
char *end;
/* No library routine sets errno to 0 - but this one needs to */
int old_errno = errno;
errno = 0;
/* Skip leading white space */
while (isspace((unsigned char)*str))
str++;
/* Detect optional sign */
if (*str == '+')
str++;
else if (*str == '-')
{
sign = -1;
str++;
}
/* Next character must be a digit */
if (!isdigit((unsigned char)*str))
{
errno = EINVAL;
return -1;
}
/* Convert seconds part of string */
sec = strtol(str, &end, 10);
if (end == str || ((sec == LONG_MAX || sec == LONG_MIN) && errno == ERANGE))
{
errno = EINVAL;
return -1;
}
if (*end != '\0' && !isspace((unsigned char)*end))
{
if (*end++ != '.')
{
errno = EINVAL;
return -1;
}
if (*end == '\0')
nsec = 0;
else if (isdigit((unsigned char)*end))
{
char *frac = end;
nsec = strtol(frac, &end, 10);
if (end == str ||
((nsec == LONG_MAX || nsec == LONG_MIN) && errno == ERANGE) ||
(nsec < 0 || nsec >= NS_PER_SECOND) || (end - frac > 9))
{
errno = EINVAL;
return -1;
}
for (int i = 0; i < 9 - (end - frac); i++)
nsec *= 10;
}
}
/* Allow trailing white space - only */
unsigned char uc;
while ((uc = (unsigned char)*end++) != '\0')
{
if (!isspace(uc))
{
errno = EINVAL;
return -1;
}
}
/* Success! */
value->tv_sec = sec * sign;
value->tv_nsec = nsec * sign;
errno = old_errno;
return 0;
}
关于C、clock_gettime,返回了不正确的纳秒值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46043743/
根据这个问题:Fractional power of units of measures in F# F# 中的度量单位不支持分数幂。 在我的应用程序中,有时考虑带有度量前缀的数据是有益的,例如当处理
我是一名优秀的程序员,十分优秀!