📄 x1206.html
字号:
/* Standard in kernel modules */
#include <linux/kernel.h> /* We're doing kernel work */
#include <linux/module.h> /* Specifically, a module */
/* Deal with CONFIG_MODVERSIONS */
#if CONFIG_MODVERSIONS==1
#define MODVERSIONS
#include <linux/modversions.h>
#endif
#include <linux/sched.h>
#include <linux/tqueue.h>
/* We want an interrupt */
#include <linux/interrupt.h>
#include <asm/io.h>
/* In 2.2.3 /usr/include/linux/version.h includes a macro for this, but
* 2.0.35 doesn't - 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 it's safe
* to do everything normally allowed by kernel modules.
*/
static void got_char(void *scancode)
{
printk("Scan Code %x %s.\n",
(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 won't co-exist with another handler,
* such as us, we have to disable it (free its IRQ) before we do
* anything. Since we don't know where it is, there's no way to
* reinstate it later - so the computer will have to be rebooted
* when we're done.
*/
free_irq(1, NULL);
/* Request IRQ 1, the keyboard IRQ, to go to our irq_handler.
* SA_SHIRQ means we're willing to have othe handlers on this IRQ.
* SA_INTERRUPT can be used to make the handler into a fast interrupt.
*/
return request_irq(1, /* The number of the keyboard IRQ on PCs */
irq_handler, /* our handler */
SA_SHIRQ,
"test_keyboard_irq_handler", NULL);
}
/* Cleanup */
void cleanup_module()
{
/* This is only here for completeness. It's totally irrelevant, since
* we don't have a way to restore the normal keyboard interrupt so the
* computer is completely useless and has to be rebooted.
*/
free_irq(1, NULL);
} </PRE
></FONT
></TD
></TR
></TABLE
></DIV
></DIV
></DIV
><H3
CLASS="FOOTNOTES"
>Notes</H3
><TABLE
BORDER="0"
CLASS="FOOTNOTES"
WIDTH="100%"
><TR
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="5%"
><A
NAME="FTN.AEN1222"
HREF="x1206.html#AEN1222"
><SPAN
CLASS="footnote"
>[1]</SPAN
></A
></TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="95%"
><P
>这是Linux起源的Intel架构中的标准的起名方法。</P
></TD
></TR
><TR
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="5%"
><A
NAME="FTN.AEN1299"
HREF="x1206.html#AEN1299"
><SPAN
CLASS="footnote"
>[2]</SPAN
></A
></TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="95%"
><P
>这里是译者给出的关于“bottom
half”的一点解释,来源是google上的英文资料:</P
><P
>“底部”,“bottom half”常在涉及中断的设备驱动中提到。</P
><P
>当内核接收到一个中断请求,对应的设备驱动被调用。因为在这段时间内无法处理别的任何事务,让中断处理尽快的完成并重新让内核返回正常的工作状态是非常重要的。就是因为这个设计思想,驱动的“顶部”和“底部”的概念被提出:“顶部”是被内核调用时最先被执行的部分,快速的完成一些尽量少的却是必需的工作(像对硬件或其它资源的独享访问这种必须立刻执行的操作),然后做一些设置让“底部”去完成那些要求时间相对比较宽裕的,剩下的工作。<br>
<br>
“底部”什么时候如何运作是内核的设计问题。你也许会听到“底部”的设计已经在最近的内核中被废除了。这种说法不是很确切,在新内核中其实你可以去选择怎样去执行:像软中断或任务,就像它们以前那样,还是加入任务队列,更像启动一个用户进程。</P
></TD
></TR
> <TR
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="5%"
><A
NAME="FTN.AEN1258"
HREF="x1206.html#AEN1258"
><SPAN
CLASS="footnote"
>[3]</SPAN
></A
></TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="95%"
><P
><TT
CLASS="FUNCTION"
>queue_task_irq</TT
>被一个全局的锁(有锁定作用的变量)保护着——在版本2.2中,并没有<TT
CLASS="FUNCTION"
>queue_task_irq</TT
>,但是<TT
CLASS="FUNCTION"
>queue_task</TT
>也是被一个锁保护的。</P
></TD
></TR
></TABLE
><DIV
CLASS="NAVFOOTER"
><HR
ALIGN="LEFT"
WIDTH="100%"><TABLE
SUMMARY="Footer navigation table"
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
><A
HREF="interrupthandlers.html"
ACCESSKEY="P"
>返回</A
></TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="index.html"
ACCESSKEY="H"
>返回首页</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
><A
HREF="c1289.html"
ACCESSKEY="N"
>继续</A
></TD
></TR
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
>Interrupt Handlers</TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="interrupthandlers.html"
ACCESSKEY="U"
>返回本章开始</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
>Symmetric Multi Processing</TD
></TR
></TABLE
></DIV
></BODY
>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -