2017-03-09 7 views
0

我正在写一个内核模块,设置一个定时器,在某些时期后在模块中调用回调函数。 的代码是这样的:有没有好的方法来保持内核模块加载,直到关联的定时器回调返回

static struct timer_list test_timer; 
static void timeout_cb(unsigned long data) 
{ 
    printk("cb called\n"); 
}  
static int __init timer_module_init(void) 
{ 
    init_timer(&test_timer); 
    test_timer.expires = jiffies + HZ*5; 
    test_timer.data = 0; 
    test_timer.function = timeout_cb; 
    add_timer(&test_timer); 
    return 0; 
} 

我认为系统将自动挂断,如果被调用回调函数之前卸载模块。而且,这确实发生了。

# insmod timer_test.ko && lsmod | grep timer_test && rmmod timer_test.ko 
timer_test    1034 0 ### No ref count to the module 
### After some seconds, the system hung up 

我认为这个问题的简单解决方案add_timer()之前增加模块的引用计数,并在timeout_cb()结束,保持加载,直到timeout_cb()端模块递减。

static void timeout_cb(unsigned long data) 
{ 
    printk("cb called\n"); 
    module_put(THIS_MODULE); // decrementing ref count 
}  
static int __init timer_module_init(void) 
{ 
... 
    try_module_get(THIS_MODULE); // incrementing ref count 
    add_timer(&test_timer); 
    return 0; 
} 

这似乎做工精细,但严格来说,如果模块之后module_put()返回,但是在timeout_cb()回报卸载系统将挂断。

//objdump 
static void timeout_cb(unsigned long data) 
{ 
    0: 55      push %rbp 
    1: 48 89 e5    mov %rsp,%rbp 
    4: e8 00 00 00 00   callq 9 <timeout_cb+0x9> 
    9: 48 c7 c7 00 00 00 00 mov $0x0,%rdi 
    10: 31 c0     xor %eax,%eax 
    12: e8 00 00 00 00   callq 17 <timeout_cb+0x17> 
     printk("cb called\n"); 
     module_put(THIS_MODULE); 
    17: 48 c7 c7 00 00 00 00 mov $0x0,%rdi 
    1e: e8 00 00 00 00   callq 23 <timeout_cb+0x23> 
} 
    // I think the system would hang up if the module is unloaded here. 
    23: c9      leaveq 
    24: c3      retq 
    25: 90      nop 

有没有好的方法来保持模块加载,直到timeout_cb()完全返回?

回答

0

module_exit功能,你需要禁用定时器。你可以用同步方式使用

timer_del_sync(&test_timer); 

这会保证定时器的回调在返回时不会执行。因此,只有两种变体是可能的:

  1. 定时器在执行回调之前已被禁用。由于停用,回调执行永远不会发生。

  2. 定时器已被禁用,回调已完成。

您可以用module_put/try_module_get一个这种方法结合起来,让您的回调将在任何情况下执行。

+0

谢谢你的回答!我会把你的答案和我的方法结合起来。 –

相关问题