ubuntu 内核模块编译——中断
author:suzhaoda
首先,要声明两个变量 ,用两个模块参数 interface
和 irq
来指明我们要使用的接口 ,并使用 module_param()(注意:MODUL_PARM()函数在2.6.1以后的版本不是用了) 和 MODULE_PARM_DESC
来捕获参数.
函数 request_irq()
将您的函数添加到选定的 IRQ 行的处理程序列表.定义:
int request_irq(unsigned int irq,
void (*handler)(int, void *, struct pt_regs *),
unsigned long irqflags,
const char *devname,
void *dev_id);
irq
是中断号。
handler
是一个指针,指向处理中断的函数。
irqflags 使用RQF_SHARED就可以了, 表明我们的处理程序支持与其他处理程序共享 IRQ。
devname
是设备的简称,显示在 /proc/interrupts
列表中。我们将使用 interface
变量中的值,它是作为模块参数接收到的。
dev_id
是设备 ID。这个参数通常设置为 NULL,但是,如果需要共享 IRQ,以使得稍后那个 IRQ 被free_irq()
释放时,正确的设备会被放开,
那么它需要是 non-NULL 的。由于它是 void *
,所以它可以指向任何内容,不过,通常的做法是传递驱动程序的设备结构体。
在此,我们将使用一个指向 irq
变量的指针。
如果成功,request_irq()
将返回 0。
其余要做的全部事情就是编写 myinterrupt()
处理程序函数。它的声明已经间接通过 request_irq()
的参数说明了:
void (*handler)(int, void *, struct pt_regs *)
。
第一个参数是中断号,
第二个参数是在 request_irq
中所使用的设备 ID,
第三个参数持有一个指向某个结构体的指针,结构体中容纳的是在服务那个中断之前的处理器寄存器和状态。
这个函数需要返回某些内容。由于这不是一个真正的驱动程序,而只是研究中断,所以应该返回 IRQ_NONE
。
通过返回 IRQ_HANDLED
,我们可以宣称这是设备的真正驱动程序,不需要任何其他驱动程序来处理这个中断。
程序代码:
/*myirqtest*/
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/interrupt.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("SUZHAODA");
MODULE_DESCRIPTION("Myirqtest");
static int irq;
static char *interface = NULL;
/*
*MODULE_PARM(name,type)
*The first parmeters is the parameters name,
*The second parmeters is the data type.
*/
module_param(interface,charp,0644);
MODULE_PARM_DESC(interface, "A network interface");
module_param(irq,int,0644);
MODULE_PARM_DESC(irq,"The IRQ of the network interface");
/*
*irq function define
*The first parmeters is irq number.
*The function handler is pointer which point to the interrupt function.
*The parmeter irqflags = SA_SHIRQ,it represent that the interrupt funciton
*support the shared IRQ
*The parmeter devname is the device name.
*The last parmeter is the device ID.We usally set it NULL
*/
/*int request_irq(unsigned int irq,
void (*handler)(int,void *,struct pt_regs *),
unsigned long irqflags,
const char *devname,
void *dev_id);
*/
static irqreturn_t myinterrupt(int irq,
void *dev_id,
struct pt_regs *regs)
{
static int mycount = 0;
if(mycount < 10)
{
printk("Interrupt!/n");
mycount++;
}
return IRQ_NONE;
}
static int __init myirqtest_init(void)
{
if(request_irq(irq,&myinterrupt,IRQF_SHARED,interface,&irq))
{
printk(KERN_ERR "myirqtest:cannot register IRQ %d/n",irq);
return -EIO;
}
printk("Requst on IRQ %d succeeded/n",irq);
return 0;
}
/*
*if succeed, return 0
*/
static void __exit myirqtest_exit(void)
{
free_irq(irq,&irq);
printk("freeing IRQ %d/n",irq);
return;
}
module_init(myirqtest_init);
module_exit(myirqtest_exit);
makefile:
obj-m := myirqtest.o
KERNELDIR := /lib/modules/$(shell uname -r)/build
default:
make -C $(KERNELDIR) M=$(shell pwd) modules
clean:
rm -rf *.o *.mod.c *.ko *.symvers *.markers *.orders
最后:
在终端输入sudo make
sudo insmod **.ko interface=** irq=**
dmesg
就会看到结果。
上述**:是你要替换的地方;