request_irq+ work queue Intel架构中的键盘(rhel5 2.6.18测试通过)

本文介绍了一个Linux内核模块的实现方式,该模块通过键盘中断来读取扫描码,并使用工作队列将非时间关键任务推迟到安全时刻执行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/*
  *  intrpt.c - An interrupt handler.
  *
  *  Copyright (C) 2001 by Peter Jay Salzman
  */

/*
  * The necessary header files
  */

/*
  * Standard in kernel modules
  */
#include <linux/kernel.h>      /* We're doing kernel work */
#include <linux/module.h>      /* Specifically, a module */
#include <linux/sched.h>
#include <linux/workqueue.h>
#include <linux/interrupt.h>   /* We want an interrupt */
#include <asm/io.h>

#define MY_WORK_QUEUE_NAME "WQsched.c"

static struct workqueue_struct *my_workqueue;

/*
  * 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 puts the non time critical
  * part into the work queue. This will be run when the kernel considers it safe.
  */
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 int initialised = 0;
        static unsigned char scancode;
        static struct work_struct task;
        unsigned char status;

        /*
          * Read keyboard status
          */
        status = inb(0x64);
        scancode = inb(0x60);

        if (initialised == 0) {
               INIT_WORK(&task, got_char, &scancode);
               initialised = 1;
        } else {
               PREPARE_WORK(&task, got_char, &scancode);
        }

        queue_work(my_workqueue, &task);

        return IRQ_HANDLED;
}

/*
  * Initialize the module - register the IRQ handler
  */
int init_module()
{
        my_workqueue = create_workqueue(MY_WORK_QUEUE_NAME);

        /*
          * 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",
                          (void *)(irq_handler));
}

/*
  * 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);
}

/*
  * some work_queue related functions are just available to GPL licensed Modules
  */
MODULE_LICENSE("GPL");

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值