2017-09-17 3 views
0

J'écris un exemple de module noyau simple sur l'utilisation du gestionnaire d'interruption. Le module interrompt les interruptions du clavier. Il lit les informations pertinentes à partir du clavier, puis met des informations sur la touche que vous avez appuyée. Il insmode avec succès le module dans le noyau et interrompt bien le travail.
Cependant, quand je fais le module rmmod, la LED sur Caps Lock clignote et mon PC est gelé (je le lance sur la machine Vmware). Je pense que j'ai les bugs dans la fonction __exit. Mais je ne sais pas comment réparer. Quelqu'un peut-il m'aider? Merci beaucoup.
Le code:Programmation du module noyau (gestionnaire d'interruption)

/* 
* An interrupt handler 
*/ 

#include <linux/kernel.h> 
#include <linux/module.h> 
#include <linux/sched.h> 
#include <linux/workqueue.h> 
#include <linux/interrupt.h> 
#include <asm/io.h> 


MODULE_LICENSE("GPL"); 
MODULE_AUTHOR("Hai Dang Hoang"); 

/* 
* This function services keyboard interrupts. It reads the relevant 
* information from the keyboard and then puts information about Key that pressed 
* This example only has 3 key: ESC, F1, and F2 
*/ 

irqreturn_t irq_handler(int irq, void *dev_id, struct pt_regs *regs) 
{ 
/* 
* This variables are static because they need to be 
* accessible (through pointers) to the bottom half routine. 
*/ 

    static unsigned char scancode; 
    unsigned char status; 

/* 
* Read keyboard status 
*/ 
    status = inb(0x64); 
    scancode = inb(0x60); 

switch (scancode) 
{ 
    case 0x01: printk (KERN_INFO "! You pressed Esc ...\n"); 
       break; 
    case 0x3B: printk (KERN_INFO "! You pressed F1 ...\n"); 
       break; 
    case 0x3C: printk (KERN_INFO "! You pressed F2 ...\n"); 
       break; 
    default: 
       break; 
} 

    return IRQ_HANDLED; 
} 

/* 
* Initialize the module - register the IRQ handler 
*/ 
static int __init irq_ex_init(void) 
{ 
    /* Free interrupt*/ 
    free_irq(1,NULL); 
    return request_irq (1, (irq_handler_t) irq_handler,IRQF_SHARED, "test_keyboard_irq_handler",(void *)(irq_handler)); 
} 

static void __exit irq_ex_exit(void) 
{ 
    free_irq(1,NULL); 
} 

module_init(irq_ex_init); 
module_exit(irq_ex_exit); 

Ou vous pouvez voir mon code sur mon lien GitHub: Example interrupt handler

+0

Je suis curieux de savoir comment vous avez exécuté la commande rmmod, car le gestionnaire de votre module ne supporte pas les entrées alphabétiques. – Ash

+0

que voulez-vous dire les entrées de l'alphabet? –

+0

vous avez supprimé le module de clavier intégré dans votre fonction init, maintenant votre module est seul responsable des interruptions de clavier. Étant donné que le gestionnaire d'interruption de votre module est implémenté pour ESC, F1 et F2, comment le terminal prend des entrées pour "rmmod", je suis très nouveau pour les pilotes de périphériques s'il vous plaît aidez-moi à comprendre cela. – Ash

Répondre

2

Votre exemple ne gère pas une IRQ aléatoire. Il gère une interruption critique pour travailler avec la machine.

Au début de votre inscription, vous supprimez le gestionnaire d'interruption précédent. Votre problème est que vous n'avez pas réussi à le réinstaller une fois que vous avez supprimé le vôtre.

Le résultat est que, lorsque vous rmmod votre module, personne ne gère l'interruption du clavier.

+0

Je ne suis pas sûr de ce que vous voulez dire? Pouvez-vous écrire le code fixe? Je l'apprécie –

+0

@HaiDang Je ne suis pas sûr qu'il existe un moyen simple de vérifier qui est le gestionnaire actuel. Sans cela, il n'est pas simple d'écrire le code dont vous avez besoin. Je vous suggère de rechercher une interruption inutilisée pour votre projet d'apprentissage. –

0

S'il vous plaît changer le code:

static void __exitrq_ex_exit(void) 
{ 
    free_irq(1, NULL); 
} 

dans:

static void __exitrq_ex_exit(void) 
{ 
    free_irq(1, (void*)irq_handler); 
} 

Vous devez laisser le noyau savoir quel gestionnaire que vous souhaitez supprimer. Puisque vous utilisez la fonction irq_handler() comme dev_id, vous devez l'utiliser à nouveau pour supprimer le mode sans supprimer le gestionnaire d'interruption de clavier d'origine.