如何在Linux内核模块中添加定期计时器callback函数

我正在开发一个Linux内核模块,该模块注册来自定制电路板的中断的callback函数,并将接收到的数据置于字符设备接口后面的队列中,以供应用程序处理。 即使主板没有中断,该模块也需要不断监控和测量来自主板的中断和数据,所以还有另外一个按时间触发的callback。

当前实现使用RTC中断作为常量定时器源。 我禁用内核RTC驱动程序( CONFIG_RTC_DRV_CMOS )并请求IRQ 8并挂接定时器callback作为RTC中断处理程序。 RTC芯片每秒产生一次中断。

问题是我们不得不失去一些Linux以这种方式pipe理时间的能力,因为只有一个rtc-cmos或者板子模块可以一次加载(显然我们select了板子模块)。

Linux内核来自Debian 7.2稳定版本的linux-source软件包,版本为3.2+46 。 目标架构是i386个人电脑。

我不是一个内核开发人员,所以对内核模块开发没有太多的了解,但是我试图find自己的方式,而这些对我来说是最接近解决scheme的东西:

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

我想可能有一个简单和标准的方法来做到这一点,我会很高兴,如果有人会评论这些解决scheme或build议其他人。

也许有一个标准的内核API

当然有。 在内核模块中需要定时器可能并不少见。

我不太了解API,但我知道它存在。 如果你打算正确地编写一个内核模块,你应该得到一本书或其他东西; 有几个。 1无论如何,一个传统的方法是:

 #include <linux/timer.h> schedule_timeout(jiffies); 

那是一种被动的睡眠。 Jiffies是基于处理器内的250 HZ滴答的单元,虽然这可能是可配置的。 这个头文件还有其他各种功能,下面是关于 2.6内核的简要讨论 ,但是我认为3.x必须与这个兼容,因为包括驱动程序在内的很多源代码都比这个更早。 有一个简单的方法来找出当然。

如果你想延迟一秒,Jiffies可能没问题。 由于调度程序的延迟,毫秒级被动睡眠的粒度是一个常规内核的问题,但ktime.h中也有一个纳秒粒度API(该链接再次来自2.6内核,但该文件仍然是2005年的3.11来源,所以没有改变)。 请记住,linux也具有纳秒粒度的用户空间计时器,但这并不意味着它们实际上会因为调度程序延迟(在内核空间中被动定时器也是如此)而在该级别上进行计时。

您可以访问RTC而不是使用处理器/内核tick,但有一些缺点:

  • 并不是所有的系统实际上都有。
  • 意味着繁忙的循环。

并没有真正的优势。 AFAIK RTC 被认为比处理器滴答更准确。

1另一个你明智的使用的资源是Linux内核邮件列表 (LKML),这是开发者所在的位置,他们的确回答了问题。 被警告的名单有成百上千的消息每天的数量。