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.
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;
}
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/
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.
© 2022 - 2024 — McMap. All rights reserved.
jiffles
) – Stotinkasetitimer
sets a timer in user space. – Lefthand