2016-01-22 52 views
1

我正在寫一個內核模塊,我需要定期觸發一個函數。該函數將訪問隊列並處理其元素。隊列中元素的數量是動態的,因此處理時間也是如此。如果回調函數的處理時間是動態的,如何使用hrtimer?

在下面的代碼中,我添加了1ms睡眠來表示處理時間。我得到這個錯誤:[116588.117966] BUG: scheduling while atomic: systemd-journal/408/0x00010000。如果我的理解是正確的,那麼發生這種情況是因爲當hr_timer的失效時間僅爲1us時,我試圖睡1ms。我可以增加這個到期時間,但是隊列的處理時間有時可能超過秒,有時甚至是幾小時。請幫我實現這一點。

unsigned long timer_interval_ns = 1e3; 
static struct hrtimer hr_timer; 

enum hrtimer_restart timer_callback(struct hrtimer *timer_for_restart) 
{ 
    uint64_t rawtime; 
    struct timespec curtime; 
    ktime_t currtime , interval; 

    /* My Operations would take ~ 1ms, so adding 1ms for simplicity*/
    msleep(1); 

    currtime = ktime_get(); 
    interval = ktime_set(0,timer_interval_ns); 

    hrtimer_forward(timer_for_restart, currtime, interval); 

    return HRTIMER_RESTART; 
} 

static int __init timer_init(void) { 
    ktime_t ktime = ktime_set(0, timer_interval_ns); 
    hrtimer_init(&hr_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); 
    hr_timer.function = &timer_callback; 
    hrtimer_start(&hr_timer, ktime, HRTIMER_MODE_REL); 
    return 0; 
} 
+0

「計劃,而原子」 表示你已經嘗試找個地方睡覺,你不應該 - 像內自旋鎖保護關鍵部分或**中斷處理程序**。 – LPs

+0

@LPs,那麼你有什麼想法爲什麼上面的簡單代碼會拋出這樣的錯誤 – Karthik

+0

我的猜測是,msleep不能在定時器回調中使用。如果你想在定時器回調的上下文中模擬一個長時間的執行(它有點類似於中斷上下文),你應該使用一個活動循環足夠長的時間。 –

回答

1

BUG:調度而原子

此消息意味着,當你在一個原子上下文你試圖安排一些其他任務。如果函數在原子上下文中運行,則該函數不能執行,並調用調度器(又名睡眠)。

當你打電話給msleep(1)時,你實際上是要求內核安排一些其他的任務,因爲1毫秒你沒有任何事情要做,你要求內核使用這段時間去做一些有用的事情。但是這在原子上下文中是不允許的。運行在原子上下文中的函數必須完成它們的執行而不會有任何中斷。

另一個睡眠功能的例子,你可能有誘惑使用是kmalloc。如果您在原子上下文中需要它,那麼使用GFP_ATOMIC標誌以便擁有一個不會睡眠的原子分配(計劃)。

原子上下文的另一個例子是中斷處理函數。

您可能與msleep(1)可能有的另一個問題是不能保證它會睡1毫秒。它太短而無法保證。事實上,建議使用大於或等於20毫秒的睡眠時間。如果您需要較短的睡眠時間,則使用延遲功能。

閱讀以下鏈接:

https://en.wikipedia.org/wiki/Linearizability

https://lwn.net/Articles/274695/

https://www.kernel.org/doc/Documentation/timers/timers-howto.txt

相關問題