我正在编写一个内核模块,我需要定期触发一个函数。该函数将访问队列并处理其元素。队列中的元素数量是动态的,因此处理时间也是如此。
在下面的代码中,我添加了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 :(得分:3)
BUG:原子调度
此消息表示当您处于原子上下文时,您尝试安排其他任务。
为了简化(所以,不完美和正统的解释):如果函数在原子上下文中运行,则此函数不能停止执行并调用调度程序(也称为休眠)。 / p>
当你调用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