C 带有等待队列挂起系统的Linux驱动程序代码

C 带有等待队列挂起系统的Linux驱动程序代码,c,linux,multithreading,linux-device-driver,C,Linux,Multithreading,Linux Device Driver,我已经编写了一个示例linux设备驱动程序代码,它将创建两个内核线程,每个线程将增加一个全局变量。我使用了等待队列来执行递增变量的任务,每个线程将在等待队列上等待,直到计时器过期并且随机唤醒每个线程 #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/errno.h> #incl

我已经编写了一个示例linux设备驱动程序代码,它将创建两个内核线程,每个线程将增加一个全局变量。我使用了等待队列来执行递增变量的任务,每个线程将在等待队列上等待,直到计时器过期并且随机唤醒每个线程

    #include <linux/module.h>
    #include <linux/kernel.h>
    #include <linux/init.h>
    #include <linux/errno.h>
    #include <linux/semaphore.h>
    #include <linux/wait.h>
    #include <linux/timer.h>
    #include <linux/sched.h>
    #include <linux/kthread.h>

    spinlock_t my_si_lock;
    pid_t kthread_pid1;
    pid_t kthread_pid2 ;
    static DECLARE_WAIT_QUEUE_HEAD(wqueue);
    static struct timer_list my_timer;
    int kthread_num;

    /* the timer callback */   
    void my_timer_callback( unsigned long data ){   
    printk(KERN_INFO "my_timer_callback called (%ld).\n", jiffies );
        if (waitqueue_active(&wqueue)) {
                wake_up_interruptible(&wqueue);
        }
    }

    /*Routine for the first thread */
    static int kthread_routine_1(void *kthread_num)
    {
        //int num=(int)(*(int*)kthread_num);
        int *num=(int *)kthread_num;
        char kthread_name[15];
        unsigned long flags;
        DECLARE_WAITQUEUE(wait, current);

        printk(KERN_INFO "Inside daemon_routine() %ld\n",current->pid);

        allow_signal(SIGKILL);
        allow_signal(SIGTERM);

        do{
                set_current_state(TASK_INTERRUPTIBLE);
                add_wait_queue(&wqueue, &wait);

                spin_lock_irqsave(&my_si_lock, flags);
                printk(KERN_INFO "kernel_daemon [%d] incrementing the shared data=%d\n",current->pid,(*num)++);
                spin_unlock_irqrestore(&my_si_lock, flags);

                remove_wait_queue(&wqueue, &wait);

                if (kthread_should_stop()) {
                        break;
                }

        }while(!signal_pending(current));

        set_current_state(TASK_RUNNING);
        return 0;
    }

    /*Routine for the second thread */
    static int kthread_routine_2(void *kthread_num)
    {
        //int num=(int)(*(int*)kthread_num);
        int *num=(int *)kthread_num;
        char kthread_name[15];
        unsigned long flags;
        DECLARE_WAITQUEUE(wait, current);

        printk(KERN_INFO "Inside daemon_routine() %ld\n",current->pid);

        allow_signal(SIGKILL);
        allow_signal(SIGTERM);

        do{
                set_current_state(TASK_INTERRUPTIBLE);
                add_wait_queue(&wqueue, &wait);

                spin_lock_irqsave(&my_si_lock, flags);
                printk(KERN_INFO "kernel_daemon [%d] incrementing the shared data=%d\n",current->pid,(*num)++);
                spin_unlock_irqrestore(&my_si_lock, flags);

                remove_wait_queue(&wqueue, &wait);

                if (kthread_should_stop()) {
                        break;
                }

        }while(!signal_pending(current));

        set_current_state(TASK_RUNNING);
        return 0;
    }

    static int __init signalexample_module_init(void)
    {
        int ret;

        spin_lock_init(&my_si_lock);
        init_waitqueue_head(&wqueue);
        kthread_num=1;

        printk(KERN_INFO "starting the first kernel thread with id ");
        kthread_pid1 = kthread_run(kthread_routine_1,&kthread_num,"first_kthread");
        printk(KERN_INFO "%ld \n",(long)kthread_pid1);
        if(kthread_pid1< 0 ){
                printk(KERN_ALERT "Kernel thread [1] creation failed\n");
                return -1;
        }

        printk(KERN_INFO "starting the second kernel thread with id");
        kthread_pid2 = kthread_run(kthread_routine_2,&kthread_num,"second_kthread");
        printk(KERN_INFO "%ld \n",(long)kthread_pid2);
        if(kthread_pid2 < 0 ){
                printk(KERN_ALERT "Kernel thread [2] creation failed\n");
                return -1;
        }

        setup_timer( &my_timer, my_timer_callback, 0 );

        ret = mod_timer( &my_timer, jiffies + msecs_to_jiffies(2000) );
        if (ret) {
                printk("Error in mod_timer\n");
                return -EINVAL;
        }
        return 0;
    }

    static void __exit signalexample_module_exit(void)
    {
        del_timer(&my_timer);
    }

module_init(signalexample_module_init);
module_exit(signalexample_module_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Demonstrates use of kthread");
但问题是,当我插入这个模块时,整个系统刚刚冻结,我必须重新启动机器。每次我插入模块时都会发生这种情况。我试着调试kthread代码,看看我是否错误地进入了死锁状态,但我无法找出代码的任何错误

    #include <linux/module.h>
    #include <linux/kernel.h>
    #include <linux/init.h>
    #include <linux/errno.h>
    #include <linux/semaphore.h>
    #include <linux/wait.h>
    #include <linux/timer.h>
    #include <linux/sched.h>
    #include <linux/kthread.h>

    spinlock_t my_si_lock;
    pid_t kthread_pid1;
    pid_t kthread_pid2 ;
    static DECLARE_WAIT_QUEUE_HEAD(wqueue);
    static struct timer_list my_timer;
    int kthread_num;

    /* the timer callback */   
    void my_timer_callback( unsigned long data ){   
    printk(KERN_INFO "my_timer_callback called (%ld).\n", jiffies );
        if (waitqueue_active(&wqueue)) {
                wake_up_interruptible(&wqueue);
        }
    }

    /*Routine for the first thread */
    static int kthread_routine_1(void *kthread_num)
    {
        //int num=(int)(*(int*)kthread_num);
        int *num=(int *)kthread_num;
        char kthread_name[15];
        unsigned long flags;
        DECLARE_WAITQUEUE(wait, current);

        printk(KERN_INFO "Inside daemon_routine() %ld\n",current->pid);

        allow_signal(SIGKILL);
        allow_signal(SIGTERM);

        do{
                set_current_state(TASK_INTERRUPTIBLE);
                add_wait_queue(&wqueue, &wait);

                spin_lock_irqsave(&my_si_lock, flags);
                printk(KERN_INFO "kernel_daemon [%d] incrementing the shared data=%d\n",current->pid,(*num)++);
                spin_unlock_irqrestore(&my_si_lock, flags);

                remove_wait_queue(&wqueue, &wait);

                if (kthread_should_stop()) {
                        break;
                }

        }while(!signal_pending(current));

        set_current_state(TASK_RUNNING);
        return 0;
    }

    /*Routine for the second thread */
    static int kthread_routine_2(void *kthread_num)
    {
        //int num=(int)(*(int*)kthread_num);
        int *num=(int *)kthread_num;
        char kthread_name[15];
        unsigned long flags;
        DECLARE_WAITQUEUE(wait, current);

        printk(KERN_INFO "Inside daemon_routine() %ld\n",current->pid);

        allow_signal(SIGKILL);
        allow_signal(SIGTERM);

        do{
                set_current_state(TASK_INTERRUPTIBLE);
                add_wait_queue(&wqueue, &wait);

                spin_lock_irqsave(&my_si_lock, flags);
                printk(KERN_INFO "kernel_daemon [%d] incrementing the shared data=%d\n",current->pid,(*num)++);
                spin_unlock_irqrestore(&my_si_lock, flags);

                remove_wait_queue(&wqueue, &wait);

                if (kthread_should_stop()) {
                        break;
                }

        }while(!signal_pending(current));

        set_current_state(TASK_RUNNING);
        return 0;
    }

    static int __init signalexample_module_init(void)
    {
        int ret;

        spin_lock_init(&my_si_lock);
        init_waitqueue_head(&wqueue);
        kthread_num=1;

        printk(KERN_INFO "starting the first kernel thread with id ");
        kthread_pid1 = kthread_run(kthread_routine_1,&kthread_num,"first_kthread");
        printk(KERN_INFO "%ld \n",(long)kthread_pid1);
        if(kthread_pid1< 0 ){
                printk(KERN_ALERT "Kernel thread [1] creation failed\n");
                return -1;
        }

        printk(KERN_INFO "starting the second kernel thread with id");
        kthread_pid2 = kthread_run(kthread_routine_2,&kthread_num,"second_kthread");
        printk(KERN_INFO "%ld \n",(long)kthread_pid2);
        if(kthread_pid2 < 0 ){
                printk(KERN_ALERT "Kernel thread [2] creation failed\n");
                return -1;
        }

        setup_timer( &my_timer, my_timer_callback, 0 );

        ret = mod_timer( &my_timer, jiffies + msecs_to_jiffies(2000) );
        if (ret) {
                printk("Error in mod_timer\n");
                return -EINVAL;
        }
        return 0;
    }

    static void __exit signalexample_module_exit(void)
    {
        del_timer(&my_timer);
    }

module_init(signalexample_module_init);
module_exit(signalexample_module_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Demonstrates use of kthread");
有谁能告诉我,我在代码中做了什么错误,导致了挂断情况

    #include <linux/module.h>
    #include <linux/kernel.h>
    #include <linux/init.h>
    #include <linux/errno.h>
    #include <linux/semaphore.h>
    #include <linux/wait.h>
    #include <linux/timer.h>
    #include <linux/sched.h>
    #include <linux/kthread.h>

    spinlock_t my_si_lock;
    pid_t kthread_pid1;
    pid_t kthread_pid2 ;
    static DECLARE_WAIT_QUEUE_HEAD(wqueue);
    static struct timer_list my_timer;
    int kthread_num;

    /* the timer callback */   
    void my_timer_callback( unsigned long data ){   
    printk(KERN_INFO "my_timer_callback called (%ld).\n", jiffies );
        if (waitqueue_active(&wqueue)) {
                wake_up_interruptible(&wqueue);
        }
    }

    /*Routine for the first thread */
    static int kthread_routine_1(void *kthread_num)
    {
        //int num=(int)(*(int*)kthread_num);
        int *num=(int *)kthread_num;
        char kthread_name[15];
        unsigned long flags;
        DECLARE_WAITQUEUE(wait, current);

        printk(KERN_INFO "Inside daemon_routine() %ld\n",current->pid);

        allow_signal(SIGKILL);
        allow_signal(SIGTERM);

        do{
                set_current_state(TASK_INTERRUPTIBLE);
                add_wait_queue(&wqueue, &wait);

                spin_lock_irqsave(&my_si_lock, flags);
                printk(KERN_INFO "kernel_daemon [%d] incrementing the shared data=%d\n",current->pid,(*num)++);
                spin_unlock_irqrestore(&my_si_lock, flags);

                remove_wait_queue(&wqueue, &wait);

                if (kthread_should_stop()) {
                        break;
                }

        }while(!signal_pending(current));

        set_current_state(TASK_RUNNING);
        return 0;
    }

    /*Routine for the second thread */
    static int kthread_routine_2(void *kthread_num)
    {
        //int num=(int)(*(int*)kthread_num);
        int *num=(int *)kthread_num;
        char kthread_name[15];
        unsigned long flags;
        DECLARE_WAITQUEUE(wait, current);

        printk(KERN_INFO "Inside daemon_routine() %ld\n",current->pid);

        allow_signal(SIGKILL);
        allow_signal(SIGTERM);

        do{
                set_current_state(TASK_INTERRUPTIBLE);
                add_wait_queue(&wqueue, &wait);

                spin_lock_irqsave(&my_si_lock, flags);
                printk(KERN_INFO "kernel_daemon [%d] incrementing the shared data=%d\n",current->pid,(*num)++);
                spin_unlock_irqrestore(&my_si_lock, flags);

                remove_wait_queue(&wqueue, &wait);

                if (kthread_should_stop()) {
                        break;
                }

        }while(!signal_pending(current));

        set_current_state(TASK_RUNNING);
        return 0;
    }

    static int __init signalexample_module_init(void)
    {
        int ret;

        spin_lock_init(&my_si_lock);
        init_waitqueue_head(&wqueue);
        kthread_num=1;

        printk(KERN_INFO "starting the first kernel thread with id ");
        kthread_pid1 = kthread_run(kthread_routine_1,&kthread_num,"first_kthread");
        printk(KERN_INFO "%ld \n",(long)kthread_pid1);
        if(kthread_pid1< 0 ){
                printk(KERN_ALERT "Kernel thread [1] creation failed\n");
                return -1;
        }

        printk(KERN_INFO "starting the second kernel thread with id");
        kthread_pid2 = kthread_run(kthread_routine_2,&kthread_num,"second_kthread");
        printk(KERN_INFO "%ld \n",(long)kthread_pid2);
        if(kthread_pid2 < 0 ){
                printk(KERN_ALERT "Kernel thread [2] creation failed\n");
                return -1;
        }

        setup_timer( &my_timer, my_timer_callback, 0 );

        ret = mod_timer( &my_timer, jiffies + msecs_to_jiffies(2000) );
        if (ret) {
                printk("Error in mod_timer\n");
                return -EINVAL;
        }
        return 0;
    }

    static void __exit signalexample_module_exit(void)
    {
        del_timer(&my_timer);
    }

module_init(signalexample_module_init);
module_exit(signalexample_module_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Demonstrates use of kthread");
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
旋转锁是我的锁;
pid_t kthread_pid1;
pid_t kthread_pid2;
静态声明等待队列头(wqueue);
静态结构计时器\u列出我的\u计时器;
int kthread_num;
/*计时器回调*/
无效我的计时器回调(无符号长数据){
printk(KERN_INFO“我的计时器回调调用(%ld)。\n)”,jiffies);
if(等待队列\活动(&W队列)){
唤醒可中断(&W队列);
}
}
/*第一个线程的例程*/
静态int kthread_例程_1(void*kthread_num)
{
//int num=(int)(*(int*)kthread_num);
int*num=(int*)kthread_num;
char kthread_name[15];
无符号长旗;
声明_WAITQUEUE(等待,当前);
printk(内核信息“在守护进程例程内()%ld\n”,当前->pid);
允许信号(SIGKILL);
允许_信号(SIGTERM);
做{
设置当前状态(任务可中断);
添加等待队列(&wqueue,&wait);
自旋锁irqsave(我的锁,标志);
printk(KERN_INFO“kernel_守护程序[%d]增加共享数据=%d\n”,当前->pid,(*num)++);
旋转解锁irqrestore(我的锁定,标志);
删除等待队列(&wqueue,&wait);
if(kthread_should_stop()){
打破
}
}而(!信号_挂起(当前));
设置当前状态(任务正在运行);
返回0;
}
/*第二个线程的例程*/
静态int kthread_例程_2(void*kthread_num)
{
//int num=(int)(*(int*)kthread_num);
int*num=(int*)kthread_num;
char kthread_name[15];
无符号长旗;
声明_WAITQUEUE(等待,当前);
printk(内核信息“在守护进程例程内()%ld\n”,当前->pid);
允许信号(SIGKILL);
允许_信号(SIGTERM);
做{
设置当前状态(任务可中断);
添加等待队列(&wqueue,&wait);
自旋锁irqsave(我的锁,标志);
printk(KERN_INFO“kernel_守护程序[%d]增加共享数据=%d\n”,当前->pid,(*num)++);
旋转解锁irqrestore(我的锁定,标志);
删除等待队列(&wqueue,&wait);
if(kthread_should_stop()){
打破
}
}而(!信号_挂起(当前));
设置当前状态(任务正在运行);
返回0;
}
静态整数初始化信号示例模块初始化(无效)
{
int ret;
自旋锁初始化(&my\u si\u lock);
初始化等待队列头(&W队列);
kthread_num=1;
printk(KERN_INFO“用id启动第一个内核线程”);
kthread_pid1=kthread_run(kthread_例程_1,&kthread_num,“第一个线程”);
printk(内核信息“%ld\n”,(长)kthread_pid1);
if(kthread_pid1<0){
printk(KERN_警报“内核线程[1]创建失败\n”);
返回-1;
}
printk(KERN_INFO“用id启动第二个内核线程”);
kthread_pid2=kthread_run(kthread_例程_2,&kthread_num,“第二个线程”);
printk(内核信息“%ld\n”,(长)kthread_pid2);
if(kthread_pid2<0){
printk(KERN_警报“内核线程[2]创建失败\n”);
返回-1;
}
设置计时器(&我的计时器,我的计时器回调,0);
ret=mod_timer(&my_timer,jiffies+msecs_to_jiffies(2000));
如果(ret){
printk(“mod_timer\n中的错误”);
返回-艾因瓦尔;
}
返回0;
}
静态无效\退出信号示例\模块\退出(无效)
{
del_计时器(&my_计时器);
}
模块_init(信号示例_模块_init);
模块退出(信号示例模块退出);
模块许可证(“GPL”);
模块描述(“演示kthread的使用”);

您需要在两个线程函数中调用
schedule()

    #include <linux/module.h>
    #include <linux/kernel.h>
    #include <linux/init.h>
    #include <linux/errno.h>
    #include <linux/semaphore.h>
    #include <linux/wait.h>
    #include <linux/timer.h>
    #include <linux/sched.h>
    #include <linux/kthread.h>

    spinlock_t my_si_lock;
    pid_t kthread_pid1;
    pid_t kthread_pid2 ;
    static DECLARE_WAIT_QUEUE_HEAD(wqueue);
    static struct timer_list my_timer;
    int kthread_num;

    /* the timer callback */   
    void my_timer_callback( unsigned long data ){   
    printk(KERN_INFO "my_timer_callback called (%ld).\n", jiffies );
        if (waitqueue_active(&wqueue)) {
                wake_up_interruptible(&wqueue);
        }
    }

    /*Routine for the first thread */
    static int kthread_routine_1(void *kthread_num)
    {
        //int num=(int)(*(int*)kthread_num);
        int *num=(int *)kthread_num;
        char kthread_name[15];
        unsigned long flags;
        DECLARE_WAITQUEUE(wait, current);

        printk(KERN_INFO "Inside daemon_routine() %ld\n",current->pid);

        allow_signal(SIGKILL);
        allow_signal(SIGTERM);

        do{
                set_current_state(TASK_INTERRUPTIBLE);
                add_wait_queue(&wqueue, &wait);

                spin_lock_irqsave(&my_si_lock, flags);
                printk(KERN_INFO "kernel_daemon [%d] incrementing the shared data=%d\n",current->pid,(*num)++);
                spin_unlock_irqrestore(&my_si_lock, flags);

                remove_wait_queue(&wqueue, &wait);

                if (kthread_should_stop()) {
                        break;
                }

        }while(!signal_pending(current));

        set_current_state(TASK_RUNNING);
        return 0;
    }

    /*Routine for the second thread */
    static int kthread_routine_2(void *kthread_num)
    {
        //int num=(int)(*(int*)kthread_num);
        int *num=(int *)kthread_num;
        char kthread_name[15];
        unsigned long flags;
        DECLARE_WAITQUEUE(wait, current);

        printk(KERN_INFO "Inside daemon_routine() %ld\n",current->pid);

        allow_signal(SIGKILL);
        allow_signal(SIGTERM);

        do{
                set_current_state(TASK_INTERRUPTIBLE);
                add_wait_queue(&wqueue, &wait);

                spin_lock_irqsave(&my_si_lock, flags);
                printk(KERN_INFO "kernel_daemon [%d] incrementing the shared data=%d\n",current->pid,(*num)++);
                spin_unlock_irqrestore(&my_si_lock, flags);

                remove_wait_queue(&wqueue, &wait);

                if (kthread_should_stop()) {
                        break;
                }

        }while(!signal_pending(current));

        set_current_state(TASK_RUNNING);
        return 0;
    }

    static int __init signalexample_module_init(void)
    {
        int ret;

        spin_lock_init(&my_si_lock);
        init_waitqueue_head(&wqueue);
        kthread_num=1;

        printk(KERN_INFO "starting the first kernel thread with id ");
        kthread_pid1 = kthread_run(kthread_routine_1,&kthread_num,"first_kthread");
        printk(KERN_INFO "%ld \n",(long)kthread_pid1);
        if(kthread_pid1< 0 ){
                printk(KERN_ALERT "Kernel thread [1] creation failed\n");
                return -1;
        }

        printk(KERN_INFO "starting the second kernel thread with id");
        kthread_pid2 = kthread_run(kthread_routine_2,&kthread_num,"second_kthread");
        printk(KERN_INFO "%ld \n",(long)kthread_pid2);
        if(kthread_pid2 < 0 ){
                printk(KERN_ALERT "Kernel thread [2] creation failed\n");
                return -1;
        }

        setup_timer( &my_timer, my_timer_callback, 0 );

        ret = mod_timer( &my_timer, jiffies + msecs_to_jiffies(2000) );
        if (ret) {
                printk("Error in mod_timer\n");
                return -EINVAL;
        }
        return 0;
    }

    static void __exit signalexample_module_exit(void)
    {
        del_timer(&my_timer);
    }

module_init(signalexample_module_init);
module_exit(signalexample_module_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Demonstrates use of kthread");
/* In kernel thread function... */

set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(&wqueue, &wait);

schedule(); /* Add this call here */

spin_lock_irqsave(&my_si_lock, flags);
/* etc... */
调用
set\u current\u state(TASK\u INTERRUPTIBLE)
设置当前进程任务结构中的状态,这允许调度程序在进程睡眠时将其移出运行队列。但是你必须告诉调度程序,“好的,我已经设置了一个新的状态。现在重新调度我。”你错过了第二步,所以更改的标志在调度程序下次决定挂起你的线程之前不会生效,并且无法知道这会发生多久,或者在发生时它正在执行哪一行代码(锁定代码中除外-不应中断)

    #include <linux/module.h>
    #include <linux/kernel.h>
    #include <linux/init.h>
    #include <linux/errno.h>
    #include <linux/semaphore.h>
    #include <linux/wait.h>
    #include <linux/timer.h>
    #include <linux/sched.h>
    #include <linux/kthread.h>

    spinlock_t my_si_lock;
    pid_t kthread_pid1;
    pid_t kthread_pid2 ;
    static DECLARE_WAIT_QUEUE_HEAD(wqueue);
    static struct timer_list my_timer;
    int kthread_num;

    /* the timer callback */   
    void my_timer_callback( unsigned long data ){   
    printk(KERN_INFO "my_timer_callback called (%ld).\n", jiffies );
        if (waitqueue_active(&wqueue)) {
                wake_up_interruptible(&wqueue);
        }
    }

    /*Routine for the first thread */
    static int kthread_routine_1(void *kthread_num)
    {
        //int num=(int)(*(int*)kthread_num);
        int *num=(int *)kthread_num;
        char kthread_name[15];
        unsigned long flags;
        DECLARE_WAITQUEUE(wait, current);

        printk(KERN_INFO "Inside daemon_routine() %ld\n",current->pid);

        allow_signal(SIGKILL);
        allow_signal(SIGTERM);

        do{
                set_current_state(TASK_INTERRUPTIBLE);
                add_wait_queue(&wqueue, &wait);

                spin_lock_irqsave(&my_si_lock, flags);
                printk(KERN_INFO "kernel_daemon [%d] incrementing the shared data=%d\n",current->pid,(*num)++);
                spin_unlock_irqrestore(&my_si_lock, flags);

                remove_wait_queue(&wqueue, &wait);

                if (kthread_should_stop()) {
                        break;
                }

        }while(!signal_pending(current));

        set_current_state(TASK_RUNNING);
        return 0;
    }

    /*Routine for the second thread */
    static int kthread_routine_2(void *kthread_num)
    {
        //int num=(int)(*(int*)kthread_num);
        int *num=(int *)kthread_num;
        char kthread_name[15];
        unsigned long flags;
        DECLARE_WAITQUEUE(wait, current);

        printk(KERN_INFO "Inside daemon_routine() %ld\n",current->pid);

        allow_signal(SIGKILL);
        allow_signal(SIGTERM);

        do{
                set_current_state(TASK_INTERRUPTIBLE);
                add_wait_queue(&wqueue, &wait);

                spin_lock_irqsave(&my_si_lock, flags);
                printk(KERN_INFO "kernel_daemon [%d] incrementing the shared data=%d\n",current->pid,(*num)++);
                spin_unlock_irqrestore(&my_si_lock, flags);

                remove_wait_queue(&wqueue, &wait);

                if (kthread_should_stop()) {
                        break;
                }

        }while(!signal_pending(current));

        set_current_state(TASK_RUNNING);
        return 0;
    }

    static int __init signalexample_module_init(void)
    {
        int ret;

        spin_lock_init(&my_si_lock);
        init_waitqueue_head(&wqueue);
        kthread_num=1;

        printk(KERN_INFO "starting the first kernel thread with id ");
        kthread_pid1 = kthread_run(kthread_routine_1,&kthread_num,"first_kthread");
        printk(KERN_INFO "%ld \n",(long)kthread_pid1);
        if(kthread_pid1< 0 ){
                printk(KERN_ALERT "Kernel thread [1] creation failed\n");
                return -1;
        }

        printk(KERN_INFO "starting the second kernel thread with id");
        kthread_pid2 = kthread_run(kthread_routine_2,&kthread_num,"second_kthread");
        printk(KERN_INFO "%ld \n",(long)kthread_pid2);
        if(kthread_pid2 < 0 ){
                printk(KERN_ALERT "Kernel thread [2] creation failed\n");
                return -1;
        }

        setup_timer( &my_timer, my_timer_callback, 0 );

        ret = mod_timer( &my_timer, jiffies + msecs_to_jiffies(2000) );
        if (ret) {
                printk("Error in mod_timer\n");
                return -EINVAL;
        }
        return 0;
    }

    static void __exit signalexample_module_exit(void)
    {
        del_timer(&my_timer);
    }

module_init(signalexample_module_init);
module_exit(signalexample_module_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Demonstrates use of kthread");
我不太清楚为什么它会导致整个系统锁定,因为系统的状态非常不可预测。由于内核线程在抓取锁和循环之前没有等待计时器过期,我不知道调度程序何时会对新的任务结构状态和许多事情采取实际行动可能同时发生。您的线程正在重复调用
add_wait_queue(&wqueue,&wait);
remove_wait_queue(&wqueue,&wait);
,s