如何在Linux内核模块中设置定期计时器回调 [英] How to setup a periodic timer callback in a Linux kernel module

查看:126
本文介绍了如何在Linux内核模块中设置定期计时器回调的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在研究一个Linux内核模块,该模块注册用于回调来自定制板的中断,并将接收到的数据放入char设备接口后面的队列中,以供应用程序处理。即使没有来自板卡的中断,该模块也需要不断地监视和测量来自板卡的中断和数据,因此它具有另一个根据时间触发的回调。



<当前的实现使用RTC中断作为恒定的定时器源。我禁用内核RTC驱动程序( CONFIG_RTC_DRV_CMOS )并请求IRQ 8,并将计时器回调作为RTC中断处理程序挂起。 RTC芯片每秒产生一次中断。



问题是我们必须失去Linux以这种方式管理时间的能力,因为只有 rtc-cmos 或板模块可以立即加载(显然我们选择了板模块)。



目标架构是i386 PC。



我不是内核开发人员,因此对内核模块开发没有太大的了解,但是我试图找到自己的方法,这些是我想到的最接近解决方案的东西:




  • 以某种方式在两个模块之间共享IRQ 8(例如 request_irq(8,rtc_handler,IRQF_SHARED,rtc_handler)?)或连锁加载IRQ处理程序。

  • 找到另一种将处理程序从内核模块挂接到RTC中断的方法。 ,而不是注册IRQ 8。

  • 找到另一个可在内核模块中使用的1秒计时器事件源,也许有一个标准的内核API,我



我想可能有一种简单而标准的方式来做到这一点,如果有人发表评论,我将感到高兴。

解决方案

Linux内核高分辨率计时器 hrtimer 是一个选项。
http://lwn.net/Articles/167897/



这是我的工作:

  #include< linux / interrupt.h> 
#include< linux / hrtimer.h>
#include< linux / sched.h>

静态结构hrtimer htimer;
静态ktime_t kt_periode;

静态void timer_init(void)
{
kt_periode = ktime_set(0,104167); //秒,纳秒
hrtimer_init(&htimer,CLOCK_REALTIME,HRTIMER_MODE_REL);
htimer.function = timer_function;
hrtimer_start(& htimer,kt_periode,HRTIMER_MODE_REL);
}

static void timer_cleanup(void)
{
hrtimer_cancel(& htimer);
}

静态枚举hrtimer_restart timer_function(struct hrtimer * timer)
{
// //在这里工作。

hrtimer_forward_now(timer,kt_periode);

返回HRTIMER_RESTART;
}


I am working on a Linux kernel module that registers a callback for interrupts that come from a custom-made board and puts the received data in a queue behind a char device interface to be processed by an application. This module needs to constantly monitor and measure the interrupts and data that comes from the board even if no interrupt comes from the board, so it has another callback that triggers according to time.

Current implementation uses RTC interrupt as a constant timer source. I disable kernel RTC drivers (CONFIG_RTC_DRV_CMOS) and request for IRQ 8 and hook the timer callback as RTC interrupt handler. Interrupts are generated every second from RTC chip.

The problem is we have to lose some of Linux's ability to manage time in this way, because only one of rtc-cmos or the board module can be loaded at once (and obviously we've chosen the board module).

Target architecture is i386 PC.

I'm not a kernel developer and so don't have a big picture on kernel module development, but I'm trying to find my way and these are nearest thing to solution that come to my mind:

  • Somehow share the IRQ 8 between both modules (maybe like request_irq(8, rtc_handler, IRQF_SHARED, rtc_handler)?) or chainload IRQ handlers.
  • Finding another way to hook a handler from a kernel module to RTC interrupt, rather than registering for IRQ 8.
  • Finding another source of 1-second timer events that can be used from within a kernel module, maybe there is a standard kernel API for that, I don't know.

I suppose there might be a simple and standard way to do this and I would be glad If anyone would comment on either of these solutions or suggest others.

解决方案

Linux kernel high-resolution timer hrtimer is an option. http://lwn.net/Articles/167897/

Here what I do:

#include <linux/interrupt.h>
#include <linux/hrtimer.h>
#include <linux/sched.h>

static struct hrtimer htimer;
static ktime_t kt_periode;

static void timer_init(void)
{
    kt_periode = ktime_set(0, 104167); //seconds,nanoseconds
    hrtimer_init (& htimer, CLOCK_REALTIME, HRTIMER_MODE_REL);
    htimer.function = timer_function;
    hrtimer_start(& htimer, kt_periode, HRTIMER_MODE_REL);
}

static void timer_cleanup(void)
{
    hrtimer_cancel(& htimer);
}

static enum hrtimer_restart timer_function(struct hrtimer * timer)
{
    // @Do your work here. 

    hrtimer_forward_now(timer, kt_periode);

    return HRTIMER_RESTART;
}

这篇关于如何在Linux内核模块中设置定期计时器回调的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆