hrtimer repeating task in the Linux kernel
My goal is to create a recurring task in the linux kernel using the hrtimer
struct. I would like it to recur every 500 ms.
However, I'm a little confused about how hrtimer
works in the linux kernel (see linux/hrtimer.h
). I know that the time is specified, and the callback should return either HRTIMER_RESTART
or HRTIMER_NORESTART
. I've found some sources online that state that the timer needs to be reset in the callback using the hrtimer_forward
method. However, the sources I've seen are a little unclear on how adding the time works. Here's the code I have so far:
static struct hrtimer timer;
static enum hrtimer_restart timer_callback(struct hrtimer *timer)
{
printk(KERN_ERR "Callbackn");
//I know something needs to go here to reset the timer
return HRTIMER_RESTART;
}
static int init_timer(void)
{
ktime_t ktime;
unsigned long delay_in_ms = 500L;
printk(KERN_ERR "Timer being set upn");
ktime = ktime_set(0,delay_in_ms*1E6L);
hrtimer_init(&timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
timer.function = &timer_callback;
printk(KERN_ERR "Timer starting to firen");
printk(KERN_ERR "in %ldms %ldn", delay_in_ms, jiffies);
hrtimer_start(&timer, ktime, HRTIMER_MODE_REL);
return 0;
}
static void clean_load_balancing_timer(void)
{
int cancelled = hrtimer_cancel(&timer);
if (cancelled)
printk(KERN_ERR "Timer still runningn");
else
printk(KERN_ERR "Timer cancelledn");
}
Can someone explain exactly how resetting the timer would work in the callback function? Thanks!
If you look in kernel/sched.c around line 170 in the function sched_rt_period_timer, you will see an example usage. The essential lines are
now = hrtimer_cb_get_time(timer);
overrun = hrtimer_forward(timer, now, rt_b->rt_period);
Now get's the timer's current time as a ktime_t and rt_b->rt_period is another ktime_t specifying the period at which to advance timer. The expiration time of the hrtimer will be continuously incremented by the period until it is greater than the current time. If it took more than one addition of the period to get the expiration time greater than the current time, the return value will greater than 1 (indicating more overrruns). It can be zero, if the timer expire didn't get advanced at all.
Reference: http://lwn.net/Articles/167897/
The API it uses is from a different version of the kernel so some of the arguments have changed. The basic idea is still the same.
以下是简单的解决方案,
#include <linux/slab.h>
#include <linux/time.h>
#include <asm/string.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/hrtimer.h>
#include <linux/ktime.h>
#define NSEC_PER_MSEC 1000000L
static struct hrtimer hr_timer;
enum hrtimer_restart enHRTimer=HRTIMER_NORESTART;
s64 i64TimeInNsec = 500 * NSEC_PER_MSEC;
enum hrtimer_restart my_hrtimer_callback( struct hrtimer *timer )
{
hrtimer_forward(timer,hrtimer_cb_get_time(timer),ktime_set(0,i64TimeInNsec));
return enHRTimer;
}
void hrtimer_event_init_module(void)
{
ktime_t kt;
enHRTimer = HRTIMER_RESTART;
//HRT init
kt = ktime_set(0, i64TimeInNsec);
hrtimer_init( &hr_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS);
hrtimer_set_expires(&hr_timer, kt);
hr_timer.function = &my_hrtimer_callback;
hrtimer_start( &hr_timer, kt, HRTIMER_MODE_ABS);
}
void hrtimer_event_cleanup_module( void )
{
//Reset
hrtimer_cancel(&hr_timer);
enHRTimer = HRTIMER_NORESTART;
printk("HR-Timer module uninstalizedn");
}
链接地址: http://www.djcxy.com/p/87882.html
上一篇: 从内核模块写入eventfd