问题描述
我正在开发一个 Linux 内核模块,该模块为来自定制板的中断注册回调,并将接收到的数据放入字符设备接口后面的队列中,以供应用程序处理.该模块即使没有来自板卡的中断,也需要不断监测和测量来自板卡的中断和数据,所以它又有一个按时间触发的回调.
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.
当前实现使用 RTC 中断作为恒定定时器源.我禁用内核 RTC 驱动程序 (CONFIG_RTC_DRV_CMOS
) 并请求 IRQ 8 并将计时器回调挂钩为 RTC 中断处理程序.RTC芯片每秒产生一次中断.
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.
问题是我们不得不失去一些 Linux 以这种方式管理时间的能力,因为一次只能加载 rtc-cmos
或板模块之一(显然我们已经选择板模块).
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).
目标架构是 i386 PC.
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:
- 以某种方式在两个模块之间共享 IRQ 8(可能像
request_irq(8, rtc_handler, IRQF_SHARED, rtc_handler)
?)或链式加载 IRQ 处理程序. - 寻找另一种方法将处理程序从内核模块挂接到 RTC 中断,而不是注册 IRQ 8.
- 找到另一个可在内核模块中使用的 1 秒计时器事件源,也许有一个标准的内核 API,我不知道.
- 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 内核高分辨率计时器 hrtimer
是一个选项.http://lwn.net/Articles/167897/
Linux kernel high-resolution timer hrtimer
is an option.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;
}
这篇关于如何在 Linux 内核模块中设置周期性定时器回调的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!