How to use timers in Linux kernel device drivers?
Asked Answered
S

3

10

I want to implement a counter in Linux device drivers which increments after every fixed interval of time. I want to do this with the help of timers. A sample code snippet would be very useful.

Scalise answered 30/5, 2012 at 8:44 Comment(3)
How often do you want to increment this? Why you even need this? (there are some counters here already, e.g. jiffles)Stotinka
I want to increment say after 10 msec. Can you give some more info regarding how to use jifflesScalise
@Pat The OP is asking how to create a timer in kernel space. While setitimer sets a timer in user space.Lefthand
C
14

Have a look at following article IBM Developerworks: Timers and Lists

There is a small example of how to use Linux kernel timers (included it here for convenience, comments are from myself, removed printk messages)

#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;
}
Christiano answered 19/6, 2012 at 9:37 Comment(1)
My "edit queue is full", so I can't post this fixed link to the IBM blog post: developer.ibm.com/tutorials/l-timers-listIntertwist
I
9

Around Linux kernel 4.15 release, void setup_timer(timer, function, data); became obsolete with an intent to remove it completely.

Instead, now we have to use

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

This can be found in linux/timer.h file.

Here's a full example of 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);

And the Makefile is

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

Note: In real life programming, it is better to check the version of the kernel we are compiling for and then use an then appropriately start the timer.

References: https://lwn.net/Articles/735887/

Impearl answered 1/9, 2020 at 0:15 Comment(0)
L
5

Depending on what you exactly want to do, you can directly use jiffies to measure time, as it has been suggested in the comments. You can also use kernel timers, and given the information in your question, they seem to be a better fit.

The kernel timers API is quite intuitive:

#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);

So you would just need to define a timer function and then initialize and start the timer.

You have several sources to further learn about this topic:

  • Understanding the Linux Kernel. This book is a sort of bible for the kernel. It is somehow outdated in some areas, but still a really good source of information.
  • Linux Device Drivers. This is a very useful book when developing device drivers. There is an online version too here. The chapter dealing with time, timers, etc. is chapter 7. This book may be also a bit outdated since it is from 2005 too.
  • Linux Kernel Development. I have not checked this book, but the good point is that it is much newer (from 2010), so you may find some updated information compared to the previous two books.
Lefthand answered 19/6, 2012 at 9:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.