在学习如何在内核模式下编程键盘中断处理的过程中,并按照下面的示例,在内核空间中加载驱动程序后出现这样的错误。
#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");
irqreturn_t irq_handler(int irq, void *dev_id, struct pt_regs *regs) {
static unsigned char scancode, 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;
}
static int __init irq_ex_init(void) {
printk (KERN_INFO "DEVICE OPEN...\n");
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) {
printk (KERN_INFO "!DEVICE CLOSE...\n");
free_irq(1,(void*)(irq_handler));
}
module_init(irq_ex_init);
module_exit(irq_ex_exit);
卸载也工作正常,但在通过insmod加载后,我得到了这样的错误。我想知道是否有人可以解释它。 我使用Ubuntu 16.04.2 LTS。
Dec 5 12:02:01 iman kernel: [ 502.506500] ------------[ cut here ]------------
Dec 5 12:02:01 iman kernel: [ 502.506510] WARNING: CPU: 1 PID: 4240 at /build/linux-hwe-zOpU13/linux-hwe-4.10.0/kernel/irq/manage.c:1484 __free_irq+0xa4/0x290
Dec 5 12:02:01 iman kernel: [ 502.506511] Trying to free already-free IRQ 1
Dec 5 12:02:01 iman kernel: [ 502.506512] Modules linked in: DDriver(OE+) Driver(OE) xt_CHECKSUM iptable_mangle ipt_MASQUERADE nf_nat_masquerade_ipv4 iptable_nat nf_nat_ipv4 nf_nat libcrc32c nf_conntrack_ipv4 nf_defrag_ipv4 xt_conntrack nf_conntrack ipt_REJECT nf_reject_ipv4 xt_tcpudp bridge stp llc ebtable_filter ebtables ip6table_filter ip6_tables iptable_filter ip_tables x_tables snd_hda_codec_hdmi eeepc_wmi asus_wmi sparse_keymap intel_rapl x86_pkg_temp_thermal intel_powerclamp coretemp crct10dif_pclmul crc32_pclmul ghash_clmulni_intel cryptd intel_cstate intel_rapl_perf joydev input_leds snd_seq_midi snd_seq_midi_event snd_hda_codec_realtek snd_hda_codec_generic snd_rawmidi snd_hda_intel snd_hda_codec lpc_ich snd_seq snd_hda_core snd_hwdep snd_seq_device snd_pcm snd_timer snd soundcore mei_me shpchp mei mac_hid kvm binfmt_misc
Dec 5 12:02:01 iman kernel: [ 502.506560] irqbypass parport_pc ppdev lp parport autofs4 hid_cherry hid_generic usbhid hid nouveau mxm_wmi i2c_algo_bit ttm drm_kms_helper ahci syscopyarea libahci sysfillrect r8169 sysimgblt mii fb_sys_fops drm wmi fjes video [last unloaded: DDriver]
Dec 5 12:02:01 iman kernel: [ 502.506584] CPU: 1 PID: 4240 Comm: insmod Tainted: G W OE 4.10.0-40-generic #44~16.04.1-Ubuntu
Dec 5 12:02:01 iman kernel: [ 502.506585] Hardware name: ASUSTeK Computer INC. V-P8H67E/V-P8H67E, BIOS 1401 12/12/2011
Dec 5 12:02:01 iman kernel: [ 502.506586] Call Trace:
Dec 5 12:02:01 iman kernel: [ 502.506593] dump_stack+0x63/0x90
Dec 5 12:02:01 iman kernel: [ 502.506596] __warn+0xcb/0xf0
Dec 5 12:02:01 iman kernel: [ 502.506598] warn_slowpath_fmt+0x5f/0x80
Dec 5 12:02:01 iman kernel: [ 502.506602] __free_irq+0xa4/0x290
Dec 5 12:02:01 iman kernel: [ 502.506604] free_irq+0x39/0x90
Dec 5 12:02:01 iman kernel: [ 502.506607] ? 0xffffffffc0183000
Dec 5 12:02:01 iman kernel: [ 502.506611] irq_ex_init+0x26/0x1000 [DDriver]
Dec 5 12:02:01 iman kernel: [ 502.506614] do_one_initcall+0x53/0x1c0
Dec 5 12:02:01 iman kernel: [ 502.506619] ? kmem_cache_alloc_trace+0x152/0x1c0
Dec 5 12:02:01 iman kernel: [ 502.506624] do_init_module+0x5f/0x1ff
Dec 5 12:02:01 iman kernel: [ 502.506629] load_module+0x1825/0x1bf0
Dec 5 12:02:01 iman kernel: [ 502.506632] ? __symbol_put+0x60/0x60
Dec 5 12:02:01 iman kernel: [ 502.506636] ? ima_post_read_file+0x7d/0xa0
Dec 5 12:02:01 iman kernel: [ 502.506640] ? security_kernel_post_read_file+0x6b/0x80
Dec 5 12:02:01 iman kernel: [ 502.506644] SYSC_finit_module+0xdf/0x110
Dec 5 12:02:01 iman kernel: [ 502.506648] SyS_finit_module+0xe/0x10
Dec 5 12:02:01 iman kernel: [ 502.506652] entry_SYSCALL_64_fastpath+0x1e/0xad
Dec 5 12:02:01 iman kernel: [ 502.506655] RIP: 0033:0x7f0f6a2a3499
Dec 5 12:02:01 iman kernel: [ 502.506656] RSP: 002b:00007fff1b8c96f8 EFLAGS: 00000202 ORIG_RAX: 0000000000000139
Dec 5 12:02:01 iman kernel: [ 502.506659] RAX: ffffffffffffffda RBX: 00007f0f6a566b20 RCX: 00007f0f6a2a3499
Dec 5 12:02:01 iman kernel: [ 502.506661] RDX: 0000000000000000 RSI: 000055649bd65246 RDI: 0000000000000003
Dec 5 12:02:01 iman kernel: [ 502.506663] RBP: 0000000000001011 R08: 0000000000000000 R09: 00007f0f6a568ea0
Dec 5 12:02:01 iman kernel: [ 502.506664] R10: 0000000000000003 R11: 0000000000000202 R12: 00007f0f6a566b78
Dec 5 12:02:01 iman kernel: [ 502.506665] R13: 00007f0f6a566b78 R14: 000000000000270f R15: 00007f0f6a5671a8
Dec 5 12:02:01 iman kernel: [ 502.506668] ---[ end trace 4b89a13407b08cea ]---
答案 0 :(得分:3)
free_irq()
调用 NULL
,您应该传递在注册IRQ期间使用的唯一处理程序。
free_irq(1,(void*)(irq_handler)); //In your case
你不应该在init函数中释放IRQ,free_irq()
应该在同一模块中进行register_irq()
调用后调用。
即使你在init函数中调用free_irq(1,(void*)(irq_handler));
,内核也会因为先前没有注册过处理程序而受到污染。
您需要让内核知道您要删除哪个处理程序。
由于您不知道哪个模块已经注册了相同的IRQ,因此逻辑是在您的模块中使用已经在代码中实现的共享IRQ。
简而言之,不要在init函数中释放IRQ。