gpt4 book ai didi

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

转载 作者:IT王子 更新时间:2023-10-29 00:25:17 25 4
gpt4 key购买 nike

我想在频率为 10 的幂时被打断,因此从/dev/rtc 启用中断并不理想。我想在两次中断之间休眠 1 毫秒或 250 微秒。

从/dev/hpet 启用周期性中断工作得很好,但它似乎在某些机器上不起作用。显然我不能在实际上没有 HPET 的机器上使用它。但是我也无法在某些将 hpet 作为时钟源的机器上运行。例如,在 Core 2 Quad 上,内核文档中包含的示例程序在设置为轮询时会在 HPET_IE_ON 处失败。

如果不直接与硬件设备驱动程序接口(interface),使用Linux提供的定时器接口(interface)会更好。在某些系统上,定时器提供了随着时间的推移更加稳定的周期性中断。也就是说,由于 hpet 不能准确地以我想要的频率中断,中断开始从墙上时间漂移。但我发现有些系统的 sleep 时间(超过 10 毫秒)比使用 itimer 时要长。

这是一个使用定时器进行中断的测试程序。在某些系统上,它只会打印出一个警告,即它比目标时间睡了大约 100 微秒左右。在其他情况下,它将打印出批量警告,表明它比目标时间睡了 10 多毫秒。使用 -lrt 编译并使用 sudo chrt -f 50 [name] 运行

#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, errno, "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() 设置时遇到了同样的问题。问题是您的进程默认由 SCHED_OTHER 策略安排在静态优先级 0 上。这意味着您与所有其他进程处于一个池中,动态优先级决定。一旦有一些系统负载,就会出现延迟。

解决方案是使用 sched_setscheduler() 系统调用,将静态优先级至少增加到一个,并指定 SCHED_FIFO 策略。它会带来显着的改善。

#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。

sudo chrt -f -p 1 <pid>

请参阅我的博客文章 here .

关于linux - 如何在 Linux 中获得最准确的实时周期性中断?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5833550/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com