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

use*_*806 6 c linux driver timer linux-kernel

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

dwa*_*ter 11

请查看以下文章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;
}
Run Code Online (Sandbox Code Playgroud)


bet*_*ido 5

根据您确切想要做什么,您可以直接使用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);
Run Code Online (Sandbox Code Playgroud)

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

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

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


Gid*_*aul 5

Linux kernel 4.15左右发布,void setup_timer(timer, function, data); 变得过时,意图完全删除它。

相反,现在我们必须使用

void timer_setup(
struct timer_list *timer, 
void (*callback)(struct timer_list *),
unsigned int flags
);
Run Code Online (Sandbox Code Playgroud)

这可以在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);
Run Code Online (Sandbox Code Playgroud)

而 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
Run Code Online (Sandbox Code Playgroud)

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

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