2017-09-17 98 views
0

我编写了一个简单的关于如何使用中断处理程序的内核模块示例。该模块服务于键盘中断。它从键盘读取相关信息,然后提供有关按下的键的信息。它成功地将模块插入内核,并且中断工作。
但是,当我使用rmmod模块时,大写锁定闪烁的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

我很想知道你是如何执行rmmod命令的,因为你的模块的处理程序将不支持字母输入。 – Ash

+0

你是什么意思字母输入? –

+0

您已经在init函数中删除了内置键盘模块,现在您的模块单独响应键盘中断。 由于你的模块的中断处理程序是为ESC,F1和F2实现的,所以终端如何输入“rmmod”,我对设备驱动程序很陌生,请帮助我理解这一点。 – Ash

回答

2

您的例子不处理一些随机的IRQ。它处理对机器工作至关重要的中断。

在注册开始时,您将删除先前的中断处理程序。你的问题是,你删除自己的后,你没有重新安装它。

结果是,当你的模块rmmod没有人处理键盘中断。

+0

我不确定你的意思?你可以写固定代码吗?我很感激 –

+0

@HaiDang我不确定是否有简单的方法来检查当前处理程序是谁。没有它,编写你所需要的代码并不简单。我建议你为你的学习项目寻找一个未使用的中断。 –

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,您需要再次使用它才能在不移除原始键盘中断处理程序的情况下移除模式。