2017-03-09 3 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()が完全に復帰するまでモジュールをロードしておくとよいでしょうか? timeout_cb()は、割り込みコンテキストで呼び出されたので、私は、これは通常の方法であることを確認していないものの

答えて

0

timer_del_sync(&test_timer); 

これは、返されたときにタイマーのコールバックが実行されないことを保証します。したがって、2つの変種だけが可能です:

  1. コールバックが実行される前にタイマーが非アクティブにされました。非アクティブ化のため、コールバックの実行は決して発生しません。

  2. タイマーが無効になっていると、コールバックが終了しています。

あなたのコールバックがどのような場合に実行されるようにするには、module_put/try_module_get 1で、このアプローチを組み合わせることができます。

+0

ありがとうございました!私はあなたの答えを私のアプローチと組み合わせます。 –

関連する問題