hrtimer mengulangi tugas di kernel Linux (hrtimer repeating task in the Linux kernel)


問題描述

hrtimer mengulangi tugas di kernel Linux (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 "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");
}

Can someone explain exactly how resetting the timer would work in the callback function? Thanks!

‑‑‑‑‑

參考解法

方法 1:

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.

方法 2:

Below is the simple solution,

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

(by MasonZhehao MaoAyyappan Rathinam)

參考文件

  1. hrtimer repeating task in the Linux kernel (CC BY‑SA 3.0/4.0)

#linux-kernel #Callback #timer






相關問題

選擇 Linux I/O 調度程序 (Selecting a Linux I/O Scheduler)

Android可加載內核模塊錯誤:賦值使指針從沒有強制轉換的整數 (Android Loadable Kernel Module Error: assignment makes integer from pointer without a cast)

文件描述符中實際存儲了多少信息? (How much information is actually stored in a file descriptor?)

hrtimer mengulangi tugas di kernel Linux (hrtimer repeating task in the Linux kernel)

我可以在 C 代碼中使用 LKM 內核代碼中的“getpwuid”嗎? (Can I use "getpwuid" from kernel code in LKM in c code?)

將傳入數據包注入網絡接口 (Injecting an incoming packet to a network interface)

無法從 D3 睡眠狀態喚醒 pci 總線 (Unable to wake pci bus form D3 sleep satate)

在 Linux 中使用 DMA 的最簡單方法 (Easiest way to use DMA in Linux)

Linux I2C 通信問題 (Linux I2C communication issues)

理解 perf stat 輸出中的數字 (Make sense of numbers in perf stat output)

我如何在 amazon Linux AMI 上找到我的 Linux 發行版? (How i could find my Linux distribution on amazon Linux AMI?)

將參數傳遞給系統調用 (Passing arguments to system calls)







留言討論