2017-03-09 1 views
0

J'écris un module de noyau qui définit un temporisateur qui appelle une fonction de rappel dans le module après quelques périodes. Le code est comme ce qui suit:Est-il un bon moyen de garder le module de noyau chargé jusqu'à ce qu'un rappel de temporisateur associé retourne

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; 
} 

Je pensais que le système raccrochera si le module est déchargé avant que la fonction de rappel est appelée. Et, cela s'est réellement passé.

# 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 

Je pense une solution simple à ce problème est incrémente le compte de référence du module avant add_timer() et décrémenter à la fin de timeout_cb(), qui maintient le module chargé jusqu'à timeout_cb() extrémités.

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; 
} 

Cela semble fonctionner très bien, mais à proprement parler, le système raccroche si le module est déchargé après module_put() retours mais avant timeout_cb() retours.

//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 

est-il une bonne façon de garder le module chargé jusqu'à ce que timeout_cb() retours complètement?

Répondre

0

En fonction module_exit vous devez désactiver la minuterie. Vous pouvez le faire de manière synchronisée à l'aide

timer_del_sync(&test_timer); 

Cela GARANTISSONS le rappel de cette minuterie n'est pas exécutée lors du retour. Ainsi, seules deux variantes sont possibles:

  1. La minuterie a été désactivée avant l'exécution du rappel. En raison de la désactivation, l'exécution du rappel ne se produira jamais.

  2. La minuterie a été désactivée et le rappel est terminé.

Vous pouvez combiner cette approche avec module_put/try_module_get un, de sorte que votre rappel sera exécutée dans tous les cas.

+0

Merci pour la réponse! Je vais combiner votre réponse avec mon approche. –

0

La solution simple fonctionnera correctement parce que timeout_cb() est appelée dans le contexte d'interruption, bien que je ne sois pas sûr que ce soit la manière habituelle.

Référence: http://www.makelinux.net/ldd3/chp-7-sect-4