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

下一篇: hrtimer在Linux内核中重复执行任务