2016-01-22 70 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

相关问题