如何在Linux内核设备驱动程序中使用计时器?

时间:2012-05-30 08:44:28

标签: c linux timer linux-kernel driver

我想在Linux设备驱动程序中实现一个计数器,它在每个固定的时间间隔后递增。我想在计时器的帮助下做到这一点。示例代码段非常有用。

3 个答案:

答案 0 :(得分:10)

查看以下文章IBM Developerworks: Timers and Lists

有一个关于如何使用Linux内核定时器的小例子(为方便起见,这里包含它,注释来自我自己,删除了printk消息)

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/timer.h>

MODULE_LICENSE("GPL");

static struct timer_list my_timer;

void my_timer_callback( unsigned long data )
{
     /* do your timer stuff here */
}

int init_module(void)
{
  /* setup your timer to call my_timer_callback */
  setup_timer(&my_timer, my_timer_callback, 0);
  /* setup timer interval to 200 msecs */
  mod_timer(&my_timer, jiffies + msecs_to_jiffies(200));
  return 0;
}

void cleanup_module(void)
{
  /* remove kernel timer when unloading module */
  del_timer(&my_timer);
  return;
}

答案 1 :(得分:4)

根据您确切想要做的事情,您可以直接使用jiffies来衡量时间,就像评论中所建议的那样。您也可以使用内核定时器,并根据您的问题提供信息,它们似乎更合适。

内核定时器API非常直观:

#include <linux/timer.h>
struct timer_list {
        /* ... */
        unsigned long expires;
        void (*function)(unsigned long);
        unsigned long data;
};

void init_timer(struct timer_list *timer);
struct timer_list TIMER_INITIALIZER(_function, _expires, _data);

void add_timer(struct timer_list * timer);
int del_timer(struct timer_list * timer);

因此,您只需要定义一个计时器功能,然后初始化并启动计时器。

您有几个来源可以进一步了解此主题:

  • Understanding the Linux Kernel。本书是内核的一种圣经。它在某些方面已经过时,但仍然是一个非常好的信息来源。
  • Linux Device Drivers。在开发设备驱动程序时,这是一本非常有用的书。还有一个在线版here。关于时间,计时器等的章节是第7章。这本书也可能有点过时,因为它也是从2005年开始的。
  • Linux Kernel Development。我没有检查过这本书,但重点是它更新(从2010年开始),所以你可能会发现一些与前两本书相比的更新信息。

答案 2 :(得分:3)

在Linux内核4.15发行版中, void setup_timer(计时器,函数,数据); 已过时,旨在完全删除它。

相反,现在我们必须使用

void timer_setup(
struct timer_list *timer, 
void (*callback)(struct timer_list *),
unsigned int flags
);

这可以在 linux / timer.h 文件中找到。

这是 module_with_timer.c

的完整示例
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/jiffies.h>
#include <linux/timer.h>

MODULE_LICENSE("GPL");

static struct timer_list my_timer;

void my_timer_callback(struct timer_list *timer) {
  printk(KERN_ALERT "This line is printed after 5 seconds.\n");
}

static int init_module_with_timer(void) {
  printk(KERN_ALERT "Initializing a module with timer.\n");

  /* Setup the timer for initial use. Look in linux/timer.h for this function */
  timer_setup(&my_timer, my_timer_callback, 0);
  mod_timer(&my_timer, jiffies + msecs_to_jiffies(5000));

  return 0;
}

static void exit_module_with_timer(void) {
  printk(KERN_ALERT "Goodbye, cruel world!\n");
  del_timer(&my_timer);
}

module_init(init_module_with_timer);
module_exit(exit_module_with_timer);

Makefile是

obj-m = module_with_timer.o

# Get the current kernel version number
KVERSION = $(shell uname -r)

all:
    make -C /lib/modules/$(KVERSION)/build M=$(PWD) modules
clean:
    make -C /lib/modules/$(KVERSION)/build M=$(PWD) clean

注意:在现实生活中,最好检查要编译的内核的版本,然后使用,然后适当地启动计时器。

参考: https://lwn.net/Articles/735887/