我正在为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();

通过这样的 Action ,一切都很好。但是,当我需要映射/取消映射几个页面时(我需要它来提高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

我已经为此苦苦挣扎了一段时间,但是我没有任何想法。你有什么?

最佳答案

您必须配对嵌套的kmap/kunmap函数。

喜欢:

for (i = 0; i < page_num; i++) {
    address[i] = kmap_atomic(page[i]);
}

do_some_work();

for (i = page_num - 1; i >= 0; i--) {
    kunmap_atomic(address[i]);
}

07-25 21:53