[英]Linux Kernel Threads with spinlock freeze
我有两个内核线程,我试图以替代方式从这两个线程中打印。 我正在使用自旋锁来同步这两个线程。
int kthread_1_function(void *data)
{
while(1)
{
spin_lock(&lock1);
pr_alert("In Kernel Thread 1!!!\n");
spin_unlock(&lock2);
if(kthread_should_stop())
{
spin_unlock(&lock2);
return 1;
}
}
return 0;
}
int kthread_2_function(void *data)
{
while(1)
{
spin_lock(&lock2);
pr_alert("In Kernel Thread 2!!!\n");
spin_unlock(&lock1);
if(kthread_should_stop())
{
spin_unlock(&lock1);
return 2;
}
}
return 0;
}
在初始化模块中,我创建了这些内核线程(kthread_run),并且cleanup_module停止了这些线程(kthread_stop)。
当我尝试卸下模块时,整个系统将挂起。 通过浏览内核源代码,我可以看到spin_lock禁用了抢占,而kthread_stop尝试唤醒应该被杀死的线程,并等待该线程退出并返回。 不知道是什么导致我的系统挂起。 从逻辑上讲,它应该工作正常。
注意:初始化自旋锁时,将lock1设置为UNLOCKED,将lock2设置为LOCKED。
您在这里遇到双重解锁问题。 linux中的Spinlock是使用称为“ spinlock票务”的机制实现的。 如果您在此方案下两次解锁了自旋锁,则每隔一次尝试锁定自旋锁的操作都会导致线程永远旋转。
因此,问题在于if(kthread_should_stop())为true,您将锁解锁两次,使所有其他试图将其获取的线程卡住了。
有关自旋锁售票的更多信息: http : //en.wikipedia.org/wiki/Ticket_lock
另请注意,使用两个锁有些过时了。 我只是在两个线程之间共享一个锁。
好吧,您刚刚暗示了解决方案:在spinlock()中,抢占被禁用。 因此在spin_unlock()中将其重新启用。
现在,问题是您将spin_unlocked到了与以前不同的变量上,并且在spin_unlocked上立即启用了抢占功能,然后正常的CPU调度会将内核线程调度到另一个CPU继续执行。
并且由于您已经创建了两个kthread,因此每个kthread都可以由内核独立调度。 因此,您将最终在另一个kthread上阻塞一个kthread,每个kthread运行在不同的CPU上。
自旋锁的概念是由于多核的存在而产生的:在单核中,不需要自旋锁:当只有一个CPU时,为什么CPU不做任何事情,而是旋转锁以等待它变为非空闲状态?
最好先在自旋锁上解锁再锁定另一个,因为每个自旋锁都可以在不同的CPU本身上运行,因为CPU调度确实超出了您的控制范围。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.