如何在Linux内核模块中添加定期定时器回调 [英] How to add a peridic timer callback in a linux kernel module

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

问题描述

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

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

问题是我们必须失去Linux的这种时间管理能力,因为一次只能加载rtc-cmos或板模块中的一个(显然,我们选择了板模块). /p>

目标体系结构是i386 PC.

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

  • 以某种方式在两个模块(例如request_irq(8, rtc_handler, IRQF_SHARED, rtc_handler)?)或链式IRQ处理程序之间共享IRQ 8.
  • 找到一种将处理程序从内核模块挂接到RTC中断的方法,而不是注册IRQ 8.
  • 找到另一个可在内核模块中使用的1秒计时器事件源,也许我没有标准的内核API.

我想可能有一个简单而标准的方法来进行此操作,如果有人对这些解决方案中的任何一个发表评论或提出其他建议,我将感到很高兴.

解决方案

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

这是我的工作:

#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;
}

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天全站免登陆