setup_irq函数功能描述:函数首先根据参数irq找到数组irq_desc中对应的元素,然后调用函数__setup_irq( )把该描述符加入到IRQ链表中。函数__setup_irq( )首先对申请的中断进行正确性检查,如果满足相应的条件,则允许将新申请的中断加入IRQ链表,申请成功,返回0;否则不允许,申请失败,返回一个非0常数,一般是负数。
setup_irq文件包含
#include<linux/irq.h>
setup_irq函数声明:
在内核源码中的位置:linux-3.19.3/kernel/irq/manage.c
函数定义格式:
int setup_irq(unsigned int irq, struct irqaction *new)
setup_irq输入参数说明
参数irq是对应的中断号,相应的取值是0~16640,系统已用的是0~31,其中编号IRQ9、IRQ10、IRQ15系统保留,32~16640是用于用户定义的中断。
参数new是一个struct irqaction类型的指针,与系统中的某一irqaction标识符相对应,保存中断的相关信息,其具体定义及详细解释参考函数remove_irq( )分析文档的输入参数说明部分。
setup_irq返回参数说明
此函数的返回值是int型变量,可能的取值一般为0或负数,如果返回0,说明动态申请中断成功;如果返回值是负数,则表示动态申请中断失败,如返回值是-16,则说明申请中断的中断号已经被占用。
setup_irq实例解析
编写测试文件:setup_irq.c
头文件引用及全局变量定义:
#include <linux/interrupt.h>
#include<linux/irq.h>
#include <linux/module.h>
MODULE_LICENSE("GPL");
static int irq=10; //定义中断号
/*定义一个struct irqaction变量,irq为中断号,handler为中断处理函数,flags为中断类型,
name为中断设备名,dev_id为中断设备编号(为NULL说明设备并不真实存在)*/
static struct irqaction act =
{
.irq=10,
.handler=irq_handler,
.flags=IRQF_DISABLED,
.name="A_New_Device",
.dev_id=NULL
};
中断处理函数定义:
// 自定义中断处理函数
static irqreturn_t irq_handler(int data, void *dev_id)
{
printk("the data is :%d\n", data); //data是对应的中断号
printk("in the interrupt handler function\n");
return IRQ_NONE;
}
模块加载函数定义:
static int __init setup_irq_init(void)
{
int result=0;
printk("into setup_irq_init\n");
result=setup_irq(irq, &act); //调用函数setup_irq( )完成申请中断
printk("the result of the setup_irq is: %d\n", result);
printk("out setup_irq_init\n");
return 0;
}
模块退出函数定义:
static void __exit setup_irq_exit(void)
{
remove_irq(irq, &act); //移除申请的中断
printk("Goodbye setup_irq\n");
return;
}
模块加载、退出函数调用:
module_init(setup_irq_init);
module_exit(setup_irq_exit);
实例运行结果及分析:
首先编译程序,执行命令insmod setup_irq.ko插入内核模块,然后输入命令dmesg -c查看内核输出信息,出现如图A
所示的结果。
在模块卸载之前输入cat /proc/interrupts命令查看文件/proc/interrupts的内容,出现如图B
所示的结果。
在插入模块之前输入命令cat /proc/interrupts查看文件/proc/interrupts内容,出现如图C
所示信息。
结果分析:
由图A
所示信息可以判断函数setup_irq( )成功地动态申请了中断。图B
与图C
相比增加了一条新的记录,记录对应的中断号是10,这是函数setup_irq( )成功申请中断的效果,正好与图A
的显示信息相吻合。