c - 如果回调函数的处理时间是动态的,如何使用hrtimer?

标签 c timer linux-kernel interrupt kernel-module

我正在编写一个内核模块,我需要在其中定期触发一个函数。该函数将访问队列并处理其元素。队列中的元素数量是动态的,处理时间也是如此。

在下面的代码中,我添加了 1ms sleep 来表示处理时间。我收到此错误:[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;
}

最佳答案

BUG: scheduling while atomic

此消息表示当您处于原子上下文 中时,您尝试安排其他任务。

为了简单起见(因此,不是完美和正统的解释):如果一个函数在原子上下文中运行,则该函数不能停止它的执行并调用调度程序(也就是休眠)。

当您调用 msleep(1) 时,您实际上是在要求内核安排一些其他任务,因为在 1 毫秒内您没有任何事情要做,您要求内核使用这段时间来做有用的东西。但这在原子上下文 中是不允许的。在原子上下文中运行的函数必须在没有任何中断的情况下完成它们的执行。

另一个休眠函数的例子是 kmalloc。如果您在原子上下文中需要它,则使用 GFP_ATOMIC 标志以获得不休眠(计划)的原子分配。

原子上下文的另一个例子是中断处理函数。

msleep(1) 可能会遇到的另一个问题是不能保证它会休眠 1 毫秒。它太短了,无法保证。实际上,建议使用大于或等于 20 毫秒的休眠时间。如果您需要更短的 sleep 时间,请使用延迟功能。

阅读以下链接:

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

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

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

关于c - 如果回调函数的处理时间是动态的,如何使用hrtimer?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34943681/

相关文章:

c - Ubuntu/Xfce 禁用特定应用程序的全局快捷方式

c++ - 在 C++ 中初始化数组

c++ - (Arduino) 我想创建一个 uint8_t 数组

android - Android JNI 中的计时器

linux - 如何忽略本地 Linux 存储库上的 .*o*.cmd?

linux - VMA操作题

php - 在windows上用php执行c程序

vba - Excel 2016 在 API 计时器启动时崩溃 Workbook.close

c# - 在其回调方法中停止计时器

c - 读取系统调用表函数地址时内核模块崩溃