2012-11-03 13 views
5

Moim celem jest utworzenie powtarzającego się zadania w jądrze Linuxa przy użyciu struktury hrtimer. Chciałbym, żeby powtarzał się co 500 ms.hrtimer powtarzające się zadanie w jądrze Linuksa

Jestem jednak trochę zdezorientowany, jak działa hrtimer w jądrze Linuxa (patrz linux/hrtimer.h). Wiem, że czas jest określony, a wywołanie zwrotne powinno wrócić: HRTIMER_RESTART lub HRTIMER_NORESTART. Znalazłem niektóre źródła online, które informują, że czasomierz musi zostać zresetowany w oddzwanianiu za pomocą metody hrtimer_forward. Jednak źródła, które widziałem, są niejasne, jeśli chodzi o sposób dodawania czasu. Oto kod, który mam do tej pory:

static struct hrtimer timer; 

static enum hrtimer_restart timer_callback(struct hrtimer *timer) 
{ 
    printk(KERN_ERR "Callback\n"); 
    //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 up\n"); 

    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 fire\n"); 
    printk(KERN_ERR "in %ldms %ld\n", 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 running\n"); 
    else 
     printk(KERN_ERR "Timer cancelled\n"); 
} 

Czy ktoś może wyjaśnić, w jaki sposób resetowanie licznika czasu zadziałałoby w funkcji zwrotnej? Dzięki!

+0

Zastanawiam się, czy pamiętasz, jak skok, drugi rozbił części wstęgi ponieważ hrtimer irytować? https://www.wired.com/2012/07/leap-second-glitch-explained/ – SDsolar

Odpowiedz

7

Jeśli zajrzysz w kernelu/sched.c wokół linii 170 w funkcji sched_rt_period_timer, zobaczysz przykład użycia. Zasadnicze linie są

now = hrtimer_cb_get_time(timer);        
overrun = hrtimer_forward(timer, now, rt_b->rt_period); 

Teraz dostać się aktualny czas timera jako ktime_t i rt_b-> rt_period jest kolejnym ktime_t określając okres w którym, aby przejść timer. Czas wygaśnięcia hrtimeru będzie stale zwiększany o okres, który będzie większy niż aktualny czas. Jeśli trwało więcej niż jedno dodanie okresu, aby uzyskać czas wygaśnięcia większy od bieżącego czasu, wartość zwracana będzie większa niż 1 (wskazując więcej przekroczeń). Może wynosić zero, jeśli upłynie czas timera, nie zostanie w ogóle zaawansowany.

referencyjny: http://lwn.net/Articles/167897/

API używa jest z innej wersji jądra więc niektóre z argumentów uległy zmianie. Podstawowa idea jest wciąż taka sama.

+0

Mam również opublikowany pełny, prosty przykład tutaj: http://stackoverflow.com/questions/16920238/reliability-of- linux-kernel-dodatek-timer-w-jednym-migiem/17055867 # 17055867 – sdaau

0

Poniżej jest proste rozwiązanie,

#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 uninstalized\n"); 
} 
Powiązane problemy