在linux中使用计时器停止内核线程

时间:2015-08-05 11:34:42

标签: linux timer kernel linux-device-driver

我试图通过在函数内部调用kthread_stop()来停止内核线程,该函数将由timer调用。当我将此模块加载到内核中时,kthread在计时器中提到的指定时间后启动和停止但是在日志中给出一些错误消息。

有人帮我解决这个问题,因为我是内核线程编程的新手。这是我的代码

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/timer.h>
#include <linux/kthread.h>
#include <linux/sched.h>
MODULE_LICENSE("GPL");
struct task_struct *task;
static struct timer_list my_timer;
int thread_function(void *data) {
    printk(KERN_ALERT"IN THREAD FUNCTION");
    while(!kthread_should_stop()){
    schedule();
    }
printk(KERN_ALERT"after schedule\n");
return 1;
}

void my_timer_callback( unsigned long data ){
printk( "my_timer_callback called (%ld).\n", jiffies );
printk(KERN_ALERT"THREAD STOPPED\n");
kthread_stop(task);
}

int init_module( void ){
    int ret;
    printk("Timer module installing\n");

    //my_timer.function, my_timer.data
    setup_timer( &my_timer, my_timer_callback, 0 );

    printk( "Starting timer to fire in 2000ms (%ld)\n", jiffies );
    ret = mod_timer( &my_timer, jiffies + msecs_to_jiffies(2000) );
    if (ret) printk("Error in mod_timer\n");
    printk(KERN_INFO"-------------------- THREAD START------------------------");

    task = kthread_run(thread_function,NULL,"kerneltthread");
    printk(KERN_ALERT"Kernel Thread Name: %s\n",task->comm);

    return 0;
}

void cleanup_module( void ){
    int ret;

    ret = del_timer( &my_timer );
    if (ret) printk("The timer is still in use...\n");

    printk("Timer module uninstalling\n");

    return;
}

 MODULE_LICENSE("GPL");

这是日志中的输出消息

Aug  5 16:35:31 brao kernel: Timer module installing
Aug  5 16:35:31 brao kernel: Starting timer to fire in 2000ms (4299209850)
Aug  5 16:35:31 brao kernel: -------------------- THREAD             START------------------------
Aug  5 16:35:31 brao kernel: Kernel Thread Name: kerneltthread
Aug  5 16:35:31 brao kernel: IN THREAD FUNCTION
Aug  5 16:35:33 brao kernel: my_timer_callback called (4299211856).
Aug  5 16:35:33 brao kernel: THREAD STOPPED
Aug  5 16:35:33 brao kernel: BUG: scheduling while atomic: swapper/3/0/0x10000100
Aug  5 16:35:33 brao kernel: after schedule

1 个答案:

答案 0 :(得分:1)

计时器的功能在softirq上下文中执行,因为它不应该睡眠。但是你的my_timer_callback调用kthread_stop函数,等待直到kthread完成,即睡眠。

所以,scheduling while atomic BUG出现了:函数休眠,而不应该因为原子上下文而这样做。