如何在Linux中获得最准确的实时周期性中断?

如何在Linux中获得最准确的实时周期性中断?,第1张

概述我希望在10的幂的频率下被中断,因此启用/ dev / rtc的中断并不理想.我想在中断之间睡1毫秒或250微秒. 从/ dev / hpet启用定期中断非常有效,但它似乎在某些机器上不起作用.显然我不能在没有HPET的机器上使用它.但是我无法让它在一些可以作为时钟源使用的机器上工作.例如,在Core 2 Quad上,当设置为poll时,内核文档中包含的示例程序在HPET_IE_ON处失败. 使用 我希望在10的幂的频率下被中断,因此启用/ dev / rtc的中断并不理想.我想在中断之间睡1毫秒或250微秒.

从/ dev / hpet启用定期中断非常有效,但它似乎在某些机器上不起作用.显然我不能在没有HPET的机器上使用它.但是我无法让它在一些可以作为时钟源使用的机器上工作.例如,在Core 2 Quad上,当设置为poll时,内核文档中包含的示例程序在HPET_IE_ON处失败.@H_404_3@

使用Linux提供的itimer接口而不是直接与硬件设备驱动程序连接会更好.在某些系统上,itimer提供的定期中断随着时间的推移更加稳定.也就是说,由于hpet不能以我想要的频率中断,因此中断开始从挂起时间开始漂移.但我看到一些系统比使用itimer更长时间(10毫秒)睡眠.@H_404_3@

这是一个使用itimer进行中断的测试程序.在某些系统上,它只打印出一个警告,它在目标时间内睡眠约100微秒左右.在其他情况下,它将打印出批次警告,它在目标时间内睡了10毫秒.用-lrt编译并运行sudo chrt -f 50 [name]@H_404_3@

#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <error.h>#include <errno.h>#include <sys/ioctl.h>#include <sys/types.h>#include <sys/time.h>#include <time.h>#include <signal.h>#include <fcntl.h>#define NS_PER_SECOND 1000000000LL#define TIMESPEC_TO_NS( aTime ) ( ( NS_PER_SECOND * ( ( long long int ) aTime.tv_sec ) ) \    + aTime.tv_nsec )int main(){    // Block alarm signal,will be waited on explicitly    sigset_t lAlarm;    sigemptyset( &lAlarm );    sigaddset( &lAlarm,SIgalRM  );    sigprocmask( SIG_BLOCK,&lAlarm,NulL );    // Set up periodic interrupt timer    struct itimerval lTimer;    int lReceivedSignal = 0;    lTimer.it_value.tv_sec = 0;    lTimer.it_value.tv_usec = 250;    lTimer.it_interval = lTimer.it_value;    // Start timer    if ( setitimer( ITIMER_REAL,&lTimer,NulL ) != 0 )    {        error( EXIT_FAILURE,errno,"Could not start interval timer" );    }    struct timespec lLastTime;    struct timespec lCurrentTime;    clock_gettime( CLOCK_REALTIME,&lLastTime );    while ( 1 )    {        //Periodic wait        if ( sigwait( &lAlarm,&lReceivedSignal ) != 0 )        {            error( EXIT_FAILURE,"Failed to wait for next clock tick" );        }        clock_gettime( CLOCK_REALTIME,&lCurrentTime );        long long int lDifference =             ( TIMESPEC_TO_NS( lCurrentTime ) - TIMESPEC_TO_NS( lLastTime ) );        if ( lDifference  > 300000 )        {            fprintf( stderr,"Waited too long: %lld\n",lDifference  );        }        lLastTime = lCurrentTime;    }    return 0;}
解决方法 裸机setitimer()设置我遇到了同样的问题.
问题是默认情况下,您的进程由静态优先级0的SCHED_OTHER策略调度.这意味着您在所有其他进程的池中,并且动态优先级决定.有一些系统负载的那一刻,你会得到延迟.

解决方案是使用sched_setscheduler()系统调用,将静态优先级提高到至少一个,并指定SCHED_FIFO策略.它引起了戏剧性的改善.@H_404_3@

#include <sched.h>...int main(int argc,char *argv[]){    ...    struct sched_param schedp;    schedp.sched_priority = 1;    sched_setscheduler(0,SCHED_FIFO,&schedp);    ...}

您必须以root身份运行才能执行此 *** 作.另一种方法是使用chrt程序执行相同 *** 作,但您必须知道RT过程的PID.@H_404_3@

sudo chrt -f -p 1 <pID>

请参阅我的博客文章here.@H_404_3@ 总结

以上是内存溢出为你收集整理的如何在Linux中获得最准确的实时周期性中断?全部内容,希望文章能够帮你解决如何在Linux中获得最准确的实时周期性中断?所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/1047575.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-25
下一篇 2022-05-25

发表评论

登录后才能评论

评论列表(0条)

保存