汾阳信息网
科技
当前位置:首页 > 科技

Linux操作系统内核编程中断处理程序 (2)

发布时间:2019-09-13 19:37:07 编辑:笔名

Intel 结构上的键盘 注意:本章下面的内容都是完全针对Intel结构。如果你不是在Intel平台上的话,程序就不能工作,也不没有必要试图编译。 在写本章例子中的程序的时候我遇到一个问题。一方面,作为一个有用的例子它需要在每个人的机器上运行,得到正确的结果。另一方面,内核已经包含了所有普通设备的驱动程序,这些驱动程序和我要写的代码不一定能够共存。我找到的方法是给键盘中断写点东西,并且首先使正常的键盘中断无效。因为在内核源文件(drivers/char/keyboard.c)里它是作为一个静态符号被定义的,没有办法恢复它。在insmod这段代码前,在另一个终端sleep 120上做一次,如果要评估文件 系统的话,需要reboot。 这段代码把它自己绑定到IRQ1上,在Interl结构下这是键盘控制的IRQ。然后,当它接到一个键盘中断时,读出键盘的状态(这是inb(0x64)的目的)和由键盘返回的扫描码。然后,只要内核认为可以时,它就运行got_char给出键的编码(扫描码的前7位)和是否被按下的信息(如果第8位是0则表示按下,是1表示释放)。 ex intrpt.c /* intrpt.c - An interrupt handler. */ /* Copyright (C) 1998 by Ori Pomerantz */ /* The necessary header files */ /* Standard in kernel modules */ #include /* Were doing kernel work */ #include /* Specifically, a module */ /* Deal with CONFIG_MODVERSIONS */ #if CONFIG_MODVERSIONS==1 #define MODVERSIONS #include #endif #include #include /* We want an interrupt */ #include #include /* In 2.2.3 /usr/include/linux/version.h includes a * macro for this, but 2.0.35 doesnt - so I add it * here if necessary. */ #ifndef KERNEL_VERSION #define KERNEL_VERSION(a,b,c) ((a)*65536+(b)*256+(c)) #endif /* Bottom Half - this will get called by the kernel * as soon as its safe to do everything normally * allowed by kernel modules. */ static void got_char(void *scancode) { printk(""Scan Code %x %s. "", (int) *((char *) scancode) & 0x7F, *((char *) scancode) & 0x80 ? ""Released"" : ""Pressed""); } /* This function services keyboard interrupts. It reads * the relevant information from the keyboard and then * scheduales the bottom half to run when the kernel * considers it safe. */ void 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; static struct tq_struct task = {NULL, 0, got_char, &scancode}; unsigned char status; /* Read keyboard status */ status = inb(0x64); scancode = inb(0x60); /* Scheduale bottom half to run */ #if LINUX_VERSION_CODE > KERNEL_VERSION(2,2,0) queue_task(&task, &tq_immediate); #else queue_task_irq(&task, &tq_immediate); #endif mark_bh(IMMEDIATE_BH); } /* Initialize the module - register the IRQ handler */ int init_module() { /* Since the keyboard handler wont co-exist with * another handler, such as us, we have to disable * it (free its IRQ) before we do anything. Since we * dont know where it is, theres no way to * reinstate it later - so the computer will have to * be rebooted when were done. */ free_irq(1, NULL); /* Request IRQ 1, the keyboard IRQ, to go to our * irq_handler. */ return request_irq( 1, /* The number of the keyboard IRQ on PCs */ irq_handler, /* our handler */ SA_SHIRQ, /* SA_SHIRQ means were willing to have othe * handlers on this IRQ. * * SA_INTERRUPT can be used to make the * handler into a fast interrupt. */ ""test_keyboard_irq_handler"", NULL); } /* Cleanup */ void cleanup_module() { /* This is only here for completeness. Its totally * irrelevant, since we dont have a way to restore * the normal keyboard interrupt so the computer * is completely useless and has to be rebooted. */ free_irq(1, NULL); }

小孩咳嗽吃什么
小孩晚上咳嗽厉害怎么办
主动脉血栓
儿童流鼻血的原因及治疗