我正在尝试从beagle骨中的ADC读取数据,运行Angstrom linux发行版。我需要使用像sleep()这样的延迟机制,只在特定时间读取样本,以帮助符合特定的采样率。 我还需要计算执行时间。
这是一个示例POC(概念证明),用于演示我面临的问题:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
clock_t begin, end;
while(1)
{
begin = clock();
sleep(1); // delay for 1 sec
end = clock();
printf("Execution time = %f\n",((float)(end-begin)/CLOCKS_PER_SEC));
}
}
我总是将执行时间设为0.0;
为什么我的结果不是1?我的猜测是调用sleep()会抢占我的程序,但我不确定。
我还有什么其他选择来计算执行时间,包括延迟?
答案 0 :(得分:3)
计算执行时间的解决方案是在程序开头和结束时获取时间戳。然后有所作为。
#include <stdio.h>
#include <time.h>
int main() {
time_t begin;
time(&begin);
// Somethings
time_t end;
time(&end);
printf("Execution time %f\n", difftime(end, begin));
return (0);
}
编辑:
#include <stdio.h>
#include <time.h>
#include <sys/time.h>
int main() {
struct timeval tv;
gettimeofday(&tv, NULL);
double begin =
(tv.tv_sec) * 1000 + (tv.tv_usec) / 1000 ;
sleep(2);
gettimeofday(&tv, NULL);
double end =
(tv.tv_sec) * 1000 + (tv.tv_usec) / 1000 ;
printf("Execution time %f\n", end - begin);
return (0);
}
答案 1 :(得分:3)
Unix的原始版本不支持亚秒级计时,只有C标准的最新版本支持亚秒级“实时”(又称'wall time'或“经过时间”)。在某个时候,先添加了ftime()
,然后依次添加了gettimeofday()
和clock_gettime()
,并且在C90中将clock()
函数进行了标准化。
C标准以及至少从第7版UNIX™起使用的Unix通过time()
函数提供了每秒精度:
time_t now = time(0);
printf("%ld\n", (long)now);
第7版UNIX™(或第7版UNIX™)提供了ftime()
的毫秒级分辨率-它已包含在POSIX中,直到2004年版本(ftime()
)为止,但是它不是POSIX 2008或更高版本的一部分,尽管出于向后兼容性的原因,某些机器类型仍将支持它。
#include <sys/timeb.h>
struct timeb tb;
if (ftime(&tb) == 0)
printf("%ld.%.3d\n", (long)tb.time, tb.millitm);
POSIX还通过struct timeval
和gettimeofday()
提供(并且仍然提供)微秒分辨率计时。在POSIX 2008中被标记为过时。它可能是最便携的计时器。
#include <sys/time.h>
struct timeval tv;
if (gettimeofday(&tv, NULL) == 0)
printf("%ld.%.6d\n", (long)tv.tv_sec, tv.tv_usec);
请注意,使用gettimeofday()
时有一些注意事项-如果有人在连续的通话之间调整系统,其结果可能会受到影响。类似的注释适用于clock_gettime()
和CLOCK_REALTIME
。
POSIX正在朝着使用纳秒分辨率计时的方向发展,该计时通过struct timespec
和clock_gettime()
提供。使用clock_gettime()
,必须选择要测量的时钟。在许多情况下,CLOCK_REALTIME
是正确的选择(但如果可用,CLOCK_MONOTONIC
在某些情况下可能会更好)。
#include <time.h>
struct timespec ts;
if (clock_gettime(CLOCK_REALTIME, &ts) == 0)
printf("%ld.%.9d\n", (long)ts.tv_sec, ts.tv_nsec);
我不确定clock()
的确切来源。它不是在第7版Unix中,但在SVR4中是100,用于CLOCKS_PER_SEC。 C标准提供了clock()
函数((clock()
的POSIX规范要求CLOCKS_PER_SEC需要1,000,000; C不需要)。请注意,这并不测量经过的“墙时间”;它测量的是近似值。进程已使用的CPU时间。
自实现定义的时代开始以来,
clock()
函数应将实现的最佳近似返回到过程所使用的处理器时间。要确定以秒为单位的时间,应将
clock()
返回的值除以宏CLOCKS_PER_SEC
的值。 [XSI] ⌦CLOCKS_PER_SEC在<time.h>
中定义为一百万。 ⌫
clock_t clk = clock();
printf("%.6f\n", (double)clk / CLOCKS_PER_SEC);
由于clock()
函数测量的是CPU使用时间,而不是经过的挂钟时间,因此使用sleep()
时测量经过的时间是完全不合适的,因为休眠进程使用 no CPU时间。
C11标准提供了一些使用struct timespec
的与线程相关的函数,这些函数被定义为与该类型的POSIX定义相匹配。它还提供了功能timespec_get()
:
7.27.2.5
timespec_get
功能#include <time.h> int timespec_get(struct timespec *ts, int base);
¶2
timespec_get
函数设置ts
所指向的间隔,以基于指定的时基保存当前的日历时间。¶3如果base为
TIME_UTC
,则将tv_sec
成员设置为自实现定义的纪元以来的秒数,将其截断为整个值,并将tv_nsec
成员设置为整数纳秒,四舍五入到系统时钟的分辨率。 321)¶4如果
timespec_get
函数成功,它将返回非零值base
;否则,它将返回零。321)尽管
struct timespec
对象以纳秒分辨率描述时间,但可用分辨率取决于系统,甚至可能大于1秒。
此功能可能尚未广泛使用。例如,尽管它似乎在OpenBSD中可用,但在macOS 10.14.5 Mojave上不可用。它可能在glibc
(GNU C库)中可用,但未在Linux手册页中列出(既不在section 2 system calls的section 3 functions或https://linux.die.net中,也没有在{ {3}}或section 2 system calls的section 3 functions)。同样清楚的是,如果clock_gettime()
可用,对它实施一个体面的近似值很简单:
#if !defined(HAVE_TIMESPEC_GET) && defined(HAVE_CLOCK_GETTIME)
enum { TIME_UTC = 1 };
static inline int timespec_get(struct timespec *ts, int base)
{
assert(base != 0);
if (clock_gettime(CLOCK_REALTIME, ts) != 0)
return 0;
return base;
}
#endif /* HAVE_TIMESPEC_GET */
Windows提供了其他接口,包括https://man7.org/和GetTickCount()
,该接口返回自参考时间(最长49天)以来的毫秒数。您可能还会找到对QueryPerformanceCounter()
(一种Intel CPU指令)的引用并用于它。
time_t
值请注意,在整个代码中,我假设可以通过将值转换为time_t
并使用long
格式来打印%ld
值。这对于64位Unix系统是正确的。直到2038年1月,当当前时间与“ The(Unix)Epoch”(1970年1月1日00: 00:00 +00:00)大于2 32 -1秒-32位算术溢出。然后,强制类型转换应为long long
(保证至少为64位类型),格式应为%lld
。唯一的问题(以及现在不这样做的原因)是MS Visual Studio支持的格式-据我所知,它使用非标准名称和64位类型的格式说明符。
计算经过时间涉及计算这些函数返回的两个值之间的差。轻柔地处理结构;减去时必须处理上溢或下溢。
答案 2 :(得分:2)
确实:在sleep()
期间,该计划根本没有运行。并且由于clock()
计算CPU时间而不是挂钟时间,&#34;没有时间过去&#34;。
改为使用time()
。
答案 3 :(得分:0)
clock_gettime是用于此目的的函数。不要使用gettimeofday()...它已被弃用,并且在Opengroup和Linux手册页中有指导AGAINST使用它。
&LT;&LT;
答案 4 :(得分:0)
我使用MACRO打印经过时间。
#include <stdio.h>
#include <sys/time.h>
#include <unistd.h>
#define ELPS_TIME(func_name) do { \
struct timeval tval_before, tval_after, tval_result; \
gettimeofday(&tval_before, NULL); \
func_name; \
gettimeofday(&tval_after, NULL); \
timersub(&tval_after, &tval_before, &tval_result); \
printf("Time elapsed: %ld.%06ld seconds\n", \
(long int)tval_result.tv_sec, \
(long int)tval_result.tv_usec); } while(0)
static void test_func1() {
printf("%s:", __FUNCTION__);
sleep(1);
}
static void test_func2() {
printf("%s:", __FUNCTION__);
sleep(2);
}
int main() {
ELPS_TIME(test_func1()); //calling test_func1
ELPS_TIME(test_func2()); //calling test_func2
return 0;
}
输出:
test_func1:Time elapsed: 1.000103 seconds
test_func2:Time elapsed: 2.000974 seconds