Linux kernel 什么可能导致抢占计数更改或工作队列在原子上下文中运行?

Linux kernel 什么可能导致抢占计数更改或工作队列在原子上下文中运行?,linux-kernel,Linux Kernel,我一直在做一些模块工作,我遇到了随机发生的崩溃(通常在启动后10小时内) 内核日志消息在不同的崩溃中可能有所不同,但在某些情况下,我会得到以下消息: <4>huh, entered c90390a8 with preempt_count 0000010d, exited with c0340000? 要发生这种情况,必须发生什么(显然抢占计数发生了变化,但是什么原因造成的) 崩溃的另一个症状是,在从工作队列执行i2c时,我看到了一个调度而原子的(当然不应该是原子的,对吧?)。这可能

我一直在做一些模块工作,我遇到了随机发生的崩溃(通常在启动后10小时内)

内核日志消息在不同的崩溃中可能有所不同,但在某些情况下,我会得到以下消息:

<4>huh, entered c90390a8 with preempt_count 0000010d, exited with c0340000?
要发生这种情况,必须发生什么(显然抢占计数发生了变化,但是什么原因造成的)

崩溃的另一个症状是,在从工作队列执行i2c时,我看到了一个
调度而原子的
(当然不应该是原子的,对吧?)。这可能是什么原因造成的


我觉得这篇文章很难,但我现在真的只是在寻找任何可以排除故障的东西。

只是从我的头顶回答:“preempt\u count”是一个32位字段,它被分成子位字段,用于各种目的。子位字段在O'Reilly的《Linux内核理解》中有详细介绍。再一次,我不知道“c0340000”代表什么。但是,由于您从“0000010d”开始,并且应该以“0000010d”结束,所以无论您的计时器代码做了什么,都是相当混乱的

一个常见的原因是,如果您的计时器代码执行了类似于spin_lock_bh()的操作,但忘记执行spin_unlock_bh()。但这通常只会导致开始和结束抢占计数值之间的1位差异。但在你的情况下,你的开始值和结束值显示了巨大的变化


Michael

结束值几乎像一个地址。也许计时器中运行的代码正在写入内存中的随机位置?我正在使用的模块没有计时器,但它有一个工作队列,当这个问题出现时,我会看到来自工作队列的调度消息。无论如何,我感谢你的评论:)嗯,是的,我想c0340000可能是一个地址。但事实上,最后4个十六进制数字都是0,对于地址来说似乎太整洁了。在任何情况下,您都可以执行“cat/proc/modules”,查看是否有任何驱动程序地址包括c0340000
            int preempt_count = preempt_count();
            fn(data);
            if (preempt_count != preempt_count()) {
                printk(KERN_WARNING "huh, entered %p "
                       "with preempt_count %08x, exited"
                       " with %08x?\n",
                       fn, preempt_count,
                       preempt_count());
                BUG();
            }