我编写了一个关于如何使用中断处理程序的简单内核模块示例。该模块服务键盘中断。它从键盘读取相关信息,然后输入有关按下的键的信息。它成功地将模块insmod到内核中,并且中断工作很好
但是,当我使用rmmod模块时,Caps Lock上的LED闪烁并且我的PC被冻结(我在Vmware机器上运行它)。我想我有__exit函数中的错误。但我不知道如何解决。谁能帮我?非常感谢你。
代码:
/*
* 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);
或者您可以在我的链接GitHub上看到我的代码:Example interrupt handler
答案 0 :(得分:2)
您的示例不处理一些随机IRQ。它处理对于使用机器至关重要的中断。
在注册开始时,删除先前的中断处理程序。您的问题是,一旦删除了自己,就无法重新安装它。
结果是,当你rmmod
你的模块时,没有人正在处理键盘中断。
答案 1 :(得分:0)
请更改代码:
static void __exitrq_ex_exit(void)
{
free_irq(1, NULL);
}
成:
static void __exitrq_ex_exit(void)
{
free_irq(1, (void*)irq_handler);
}
您需要让内核知道要删除的处理程序。由于您使用函数irq_handler()
作为dev_id
,因此您需要再次使用它来删除模式而不删除原始键盘中断处理程序。