我有两个内核线程,我试图以交替的方式从这两个线程打印。我正在使用 spinlock 来同步这两个线程。
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;
}
在init模块中,我创建了这些内核线程(kthread_run),并且cleanup_module停止了这些线程(kthread_stop)。
当我尝试删除模块时,整个系统挂起。通过浏览内核源代码,我可以看到spin_lock禁用抢占,kthread_stop尝试唤醒应该被杀死的线程并等待线程退出并返回。不确定是什么让我的系统挂起。从逻辑上讲,它应该运行良好。
注意:当我初始化自旋锁时,我将lock1设置为UNLOCKED,将lock2设置为LOCKED。
答案 0 :(得分:0)
这里有双重解锁问题。 Linux中的Spinlock是使用一种名为“spinlock ticket”的机制实现的。如果你在这个方案下解锁一个自旋锁,那么每次锁定自旋锁的尝试都会导致线程永远旋转。
所以问题是如果(kthread_should_stop())为真,你解锁锁两次,让所有其他线程试图抓取它卡住。
有关螺旋锁票务的更多信息:http://en.wikipedia.org/wiki/Ticket_lock
另请注意,使用这两个锁有点过时了。我只想在两个线程之间共享一个锁。
答案 1 :(得分:0)
嗯,你刚才暗示了解决方案:在spinlock()中,抢占被禁用。所以在spin_unlock()中,它被重新启用。
现在,问题是你在一个不同于之前的变量上有spin_unlocked,并且在spin_unlocked,抢占启用后立即执行,正常的CPU调度将调度内核线程到另一个CPU继续执行。
由于您创建了两个kthread,因此每个kthread都可以由内核独立调度。所以你最终会在另一个kthread上阻塞一个kthread,每个kthread都运行在不同的CPU上。
由于多核的存在,已经创建了自旋锁概念:在单核中,不需要自旋锁:为什么CPU只会在锁上旋转等待它不自由,当只有一个时CPU?
最好在锁定另一个之前解锁自旋锁,因为每个自旋锁都可以在不同的CPU上运行,因为CPU调度实际上是你无法控制的。