带有螺旋锁冻结的Linux内核线程

时间:2014-09-16 14:50:31

标签: c multithreading module kernel spinlock

我有两个内核线程,我试图以交替的方式从这两个线程打印。我正在使用 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。

2 个答案:

答案 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调度实际上是你无法控制的。