从内核空间中的线程调度

时间:2013-12-23 04:40:56

标签: c multithreading linux-kernel scheduling

我写了一个netfilter模块,我必须在其中编写一个额外的线程来定期清理数据结构。我从线程完成每轮清理后使用schedule()函数。在使用信号量锁之前,它正常工作,除了"General Protection Fault"正在发生。所以我在insertdelete操作期间使用信号量来锁定和解锁数据结构。现在它显示了一个告诉"BUG: Scheduling while atomic"的错误。在谷歌搜索后,我得知它显示是因为schedule()函数的显式调用,不应该调用它。

有什么方法可以解决它?有没有其他方式线程将CPU产生到其他线程?

1 个答案:

答案 0 :(得分:0)

所以一个基本的总结(不能给出其他评论中指定的原因的详细答案):

信号量或互斥量将尝试获取一个锁,如果它无法实现,它将允许在等待时运行其他东西(这是通过schedule()调用完成的)。另一方面,自旋锁是一种锁定机制,它一直试图抓住一个锁,直到它成功为止并且不放弃控制(注意:还有spinlock_irq_save等,这也可以防止你被一个isr打断你可以看看这些。)

就原子而言,这意味着内核无法允许其他进程在后台运行。例如,如果您处于中断状态,则由于堆栈管理,内核无法允许其他人运行。如果你在自旋锁内,内核不能允许其他人运行,因为如果它调度另一个等待自旋锁的进程,你可能会遇到死锁情况。您可以使用in_atomic()宏来判断您是否是原子。

对于您的情况,您提到了一个插入和删除函数,这些函数显然是从原子上下文中调用的(至少在某些时候)。如果仅从原子上下文中调用它们,那么您可以使用自旋锁并完成它。如果从两者调用它们,则可以使用spinlock_irq_save(这可以防止中断中断自旋锁定区域)。再次注意,要长时间禁用中断。

如果释放中存在某些内容,您也可以将释放推迟到以后,您不希望从原子上下文中执行此操作。在这种情况下,创建一个受自旋锁保护的链表,该列表由您的删除设置。然后在你的线程中,你从列表中弹出项目,并在那里释放它们。要插入,请在锁定列表之前执行malloc。

希望这有帮助。

约翰