我正在写一个内核模块,设置一个定时器,在某些时期后在模块中调用回调函数。 的代码是这样的:有没有好的方法来保持内核模块加载,直到关联的定时器回调返回
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()
完全返回?
谢谢你的回答!我会把你的答案和我的方法结合起来。 –