【问题标题】:How to use timers in Linux kernel device drivers?如何在 Linux 内核设备驱动程序中使用定时器?
【发布时间】:2012-05-30 08:44:27
【问题描述】:

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

【问题讨论】:

  • 您希望多久增加一次?为什么你甚至需要这个? (这里已经有一些计数器,例如jiffles
  • 我想在 10 毫秒后递增。您能否提供更多有关如何使用 jiffles 的信息
  • @Pat OP 正在询问如何在内核空间中创建计时器。而setitimer 在用户空间设置了一个计时器。

标签: c linux timer linux-kernel driver


【解决方案1】:

看看下面的文章IBM Developerworks: Timers and Lists

有一个如何使用Linux内核计时器的小例子(为了方便,这里包括它,cmets来自我自己,删除了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;
}

【讨论】:

【解决方案2】:

在 Linux 内核 4.15 版本前后,void setup_timer(timer, function, data); 已过时,意图将其完全删除。

相反,现在我们必须使用

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

注意:在实际编程中,最好检查我们正在编译的内核版本,然后使用 then 适当地启动计时器。

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

【讨论】:

    【解决方案3】:

    根据您的具体目标,您可以直接使用jiffies 来测量时间,正如 cmets 中所建议的那样。您还可以使用内核计时器,并且根据您问题中的信息,它们似乎更适合。

    内核计时器 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 年开始),因此与前两本书相比,您可能会发现一些更新的信息。

    【讨论】:

      猜你喜欢
      • 2017-03-02
      • 1970-01-01
      • 2023-03-28
      • 2016-12-10
      • 2016-08-19
      • 1970-01-01
      • 2011-07-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多