我正在为 Linux 内核编写一个可加载模块,我需要在其中映射和取消映射内存页面。它发生在所有中断都被禁用时。动作顺序如下所示:
preempt_disable();
disable_all_interrupts(&interrupt_mask_saved);
kmap_atomic(page); // here i map ONE page
do_some_work();
kunmap_atomic(page); // unmapping ONE page
restore_all_interrupts(interrupt_mask_saved);
preempt_enable();
有了这样的动作,一切都很好。但是当我需要像这样映射/取消映射几个页面时(我需要它来提高 cpu 负载):
preempt_disable();
disable_all_interrupts(&interrupt_mask_saved);
for (i = 0; i < page_num; i++) {
kmap_atomic(page[ i ]); // here i map several pages
}
do_some_work();
// i tried backward unmapping but the result is the same
for (i = 0; i < page_num; i++) {
kunmap_atomic(); // unmapping several pages
}
restore_all_interrupts(interrupt_mask_saved);
preempt_enable();
系统崩溃。不处于图形模式时,错误和信息消息直接显示在终端中。将一些消息输出到屏幕后,系统会冻结。内核日志是空的,但我注意到的错误是:
scheduling while atomic
thread overran stack or stack corrupted
在 Linux 代码中,我发现 kunmap_atomic 使用 preempt_schedule() ,这可能是原子调度的原因。但是我重写了我自己的 kmap_atomic 和 kunmap_atomic 函数,没有处理抢占,它仍然不起作用。我在映射和取消映射之间执行的操作不是原因,因为我在没有它们的情况下尝试过,但它仍然冻结。
Linux 内核版本:3.0.48、Distr AltLinux 7.0.1 和 Altlinux 6.0 内核版本 3.4.62 工作正常,但我需要 3.0.48
我已经为此苦苦挣扎了一段时间,但我没有任何想法。你有什么?