内核模块工作线程调用kthread_stop后无法停止的问题排查
问题分析与解决方向
你的核心问题在于:线程被阻塞在down_interruptible(&mutex)时,kthread_stop()无法让线程主动退出——因为线程根本没机会执行kthread_should_stop()检查,而kthread_stop()不会主动发送信号中断down_interruptible的阻塞。
具体原因拆解
- 模块初始化时,
my_module_init()调用down(&mutex)持有了信号量,导致后续线程启动后,down_interruptible(&mutex)一直阻塞,无法进入循环体检查停止标志。 kthread_stop()的工作逻辑是:设置线程的停止标记,唤醒线程(仅针对kthread内部的等待队列),然后等待线程主动退出。但你的线程卡在信号量的等待队列里,kthread_stop()无法唤醒它,也不会发送信号触发down_interruptible返回-EINTR。
修复方案
方案1:先释放信号量,再调用kthread_stop
在模块退出函数中,先释放持有的信号量,让线程能从down_interruptible返回,进而检查停止标志退出:
修改后的退出函数:
static void __exit my_module_exit(void) { printk(KERN_INFO "stopping sample thread\n"); up(&mutex); // 先释放信号量,让线程从阻塞中恢复 kthread_stop(sample_thread_handle); printk(KERN_INFO "after stopping consumer thread\n"); printk(KERN_INFO "Goodbye, world!\n"); }
方案2:优化线程循环逻辑(可选)
确保线程在每次尝试获取锁失败(或被中断)后,都能重新检查停止标志:
int sample_thread(void *arg) { printk(KERN_INFO "Starting Thread..."); while(!kthread_should_stop()) { if(down_interruptible(&mutex)) { // 如果被中断,直接回到循环开头检查停止标志 continue; } // 这里可以添加获取锁后的业务逻辑 up(&mutex); // 记得用完锁释放 } printk(KERN_INFO "Leaving Thread..."); return 0; }
额外注意事项
- 内核线程中使用信号量时,必须保证锁的释放逻辑完整,避免出现永久阻塞。
kthread_stop()必须配合线程内部的kthread_should_stop()检查使用,线程需要有机会周期性检查这个标志才能正常退出。
内容的提问来源于stack exchange,提问作者Rob Goodwin
相关产品推荐
相关产品推荐

