如何在Linux用户空间中实现高度精确的计时器?
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了如何在Linux用户空间中实现高度精确的计时器?,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含2613字,纯文字阅读大概需要4分钟。
内容图文
![如何在Linux用户空间中实现高度精确的计时器?](/upload/InfoBanner/zyjiaocheng/946/6f61a84116724c1d8ca908a933298db4.jpg)
我的BeagleBoard上装有Angstrom Linux.
我想实现一个非常精确的计时器,它可以每500us触发一次.我阅读了有关hrtimers的文章,但是我发现的所有实现都是针对内核空间的.我想在用户空间中实现它.
是否有可以调用这些hrtimers的API,我可以在用户空间中使用它或以其他方式在linux中实现准确的计时器?
我已将抖动设置为几纳秒.
解决方法:
最后,经过更多的努力,我发现了一个代码,建议将timer_create(),clock_gettime()与信号处理(处理SIGALRM)结合使用,类似于Basile Starynkevitch在其评论中建议的内容.
我在时钟类型为CLOCK_MONOTONIC的1 GHz Beaglebone上尝试了500us的时间间隔.
在10000次定时器过期中,有2%的时间是500us(我忽略了纳秒级的差异).和96.6%的时间处于500 /-10us范围内.在其余时间中,平均误差不超过/-50us.
我在这里发布了稍微修改的代码版本.我对代码做了以下修改:
>在约10us的小间隔内,计数将无限递减,因此我在信号处理程序本身内部添加了对测试数量(计数)的控制.
>在运行计时器的中间添加一个printf会花费很多时间.因此,我将时差存储在数组中,然后在最后一次测试之后,我打印了所有内容.
>我认为以无符号长(即以纳秒为单位)计算时间差比以双倍(以秒为单位)计算时间差更好,因为它更准确且可能更快.因此,我修改了timerdiff宏以输出纳秒级的差异.由于我使用的间隔为500us或更小,因此差值永远不会超出unsigned long的范围.
如您所见,即使进行了修改,结果中只有2%的精确度小于1us.因此,现在我正在尝试一些其他修改,例如不运行不必要的linux进程,进一步简化程序等.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/types.h>
#include <signal.h>
#include <unistd.h>
#define NSEC_PER_SEC 1000000000L
#define MAX_TESTS 10000
#define timerdiff(a,b) (((a)->tv_sec - (b)->tv_sec) * NSEC_PER_SEC + (((a)->tv_nsec - (b)->tv_nsec)))
static struct timespec prev = {.tv_sec=0,.tv_nsec=0};
static int count = MAX_TESTS;
unsigned long diff_times[MAX_TESTS];
void handler( int signo )
{
struct timespec now;
register int i, correct=0;
if(count >= 0)
{
clock_gettime(CLOCK_MONOTONIC, &now);
diff_times[count]=timerdiff(&now, &prev);
prev = now;
count --;
}
else
{
for(i=0; i<MAX_TESTS; ++i)
{
if(diff_times[i]/1000 < 510 && diff_times[i]/1000 > 490)
{
printf("%d->\t", i);
correct++;
}
printf("%lu\n", diff_times[i]);
}
printf("-> %d\n", correct);
exit(0);
}
}
int main(int argc, char *argv[])
{
int i = 0;
timer_t t_id;
struct itimerspec tim_spec = {.it_interval= {.tv_sec=0,.tv_nsec=500000},
.it_value = {.tv_sec=1,.tv_nsec=0}};
struct sigaction act;
sigset_t set;
sigemptyset( &set );
sigaddset( &set, SIGALRM );
act.sa_flags = 0;
act.sa_mask = set;
act.sa_handler = &handler;
sigaction( SIGALRM, &act, NULL );
if (timer_create(CLOCK_MONOTONIC, NULL, &t_id))
perror("timer_create");
clock_gettime(CLOCK_MONOTONIC, &prev);
if (timer_settime(t_id, 0, &tim_spec, NULL))
perror("timer_settime");
while(1);
return 0;
}
内容总结
以上是互联网集市为您收集整理的如何在Linux用户空间中实现高度精确的计时器?全部内容,希望文章能够帮你解决如何在Linux用户空间中实现高度精确的计时器?所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。