函数:request_threaded_irq( )
文件包含:
#include<linux/interrupt.h>
函数定义:
在内核源码中的位置:linux-3.19.3/kernel/irq/manage.c
函数定义格式:
int __must_check request_threaded_irq(unsigned int irq, irq_handler_t handler, irq_handler_t thread_fn, unsigned long f lags, const char *name , void *dev)
函数功能描述:
函数request_threaded_irq( )首先对传入的参数进行正确性检查,根据传入的irq号获得数组irq_desc中以irq为下标的元素,然后动态地创建一个irqaction描述符,根据传入的参数初始化新生成的irqaction描述符,最后调用函数__setup_irq( )把该描述符加入到IRQ链表中,完成中断的动态申请及注册。
输入参数说明:
- 参数
irq
是对应的中断号,相应的取值是0~16640,系统已用的是0~31,其中编号IRQ9、IRQ10、IRQ15系统保留,32~16640是用于用户定义的中断。 -
参数
handler
是对应的中断处理函数,返回值类型是irq_handler_t,其定义见文件linux-3.19.3/include/linux/irqreturn.h。类型定义为typedef enum irqreturn irqreturn_t,可能的值是:
enum irqreturn { /*枚举类型*/
IRQ_NONE = (0<<0), //中断不是此设备发出
IRQ_HANDLED = (1<<0), //中断被此设备处理
IRQ_WAKE_THREAD = (1<<1), //中断处理函数需要唤醒中断处理线程
};
-
参数
thread_fn
是对应的中断线程处理函数,如果中断处理函数的返回值是IRQ_WAKE_THREAD,则此时注册的中断线程处理函数将被调用,此函数是对中断处理函数的补充。 -
参数
flags
是用来标识中断的类型,其定义见文件linux-3.19.3/include/linux/interrupt.h,可能的取值为:
#define IRQF_DISABLED 0x00000020 //中断使能
#define IRQF_SHARED 0x00000080 //设备共享
#define IRQF_PROBE_SHARED 0x00000100 //错序共享中断
#define __IRQF_TIMER 0x00000200 //时钟中断
#define IRQF_PERCPU 0x00000400 //CPU中断
#define IRQF_NOBALANCING 0x00000800 //中断平衡使能
#define IRQF_IRQPOLL 0x00001000 //中断轮询检测,用于设备共享的中断
#define IRQF_ONESHOT 0x00002000 //将中断保持不可用状态,直到中断处理函数结束
#define IRQF_NO_SUSPEND 0x00004000 //挂起期间不让中断保持不可用状态
// 强制中断处于重新开始状态即使设置了IRQF_NO_SUSPEND状态
#define IRQF_FORCE_RESUME 0x00008000
#define IRQF_NO_THREAD 0x00010000 //不可中断线程状态
#define IRQF_EARLY_RESUME 0x00020000 //提前恢复IRQ而不是在设备恢复期间
#define IRQF_TIMER (__IRQF_TIMER | IRQF_NO_SUSPEND | IRQF_NO_THREAD)
// 复合定义
-
参数
name
是申请的中断对应的设备名称。 -
参数
dev
是对应的设备描述符指针,如果f lags的取值是IRQF_SHARED,则dev必须是真实存在的设备;如果是IRQF_DISABLED,则dev可以赋值为NULL。
返回参数说明:
如果返回值是0则说明申请成功,如果申请不成功,则返回的值非零,一般为负数,可能的取值为-16、-38。例如,如果返回值是-16,则说明申请的中断号在内核中已被占用。
实例解析:
编写测试文件:request_threaded_irq
头文件引用及全局变量定义:
#include <linux/interrupt.h>
#include<linux/irq.h>
#include <linux/module.h>
MODULE_LICENSE("GPL");
static int irq=11; //中断号定义
中断处理函数及中断线程处理函数定义:
// 自定义中断处理函数
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_WAKE_THREAD; //触发中断线程函数执行
}
// 自定义中断线程处理函数
static irqreturn_t irq_thread_fn(int data, void *dev_id)
{
printk("the data is :%d\n", data); //data是对应中断的中断号
printk("in the interrupt thread function\n");
return IRQ_HANDLED;
}
模块加载函数定义及验证函数调用:
static int __init request_threaded_irq_init(void)
{
int result=0;
printk("into request_threaded_irq_init\n");
/* 调用request_threaded_irq( )函数,irq是对应的中断编号,irq_handler是定义的中断
处理函数,irq_thread_fn是对应的中断线程处理函数,IRQF_DISABLED是中断的类型*/
result=request_threaded_irq(irq, irq_handler, irq_thread_fn, IRQF_DISABLED, "A_New_Device", NULL);
printk("the result of the request_threaded_irq is: %d\n", result);
// 显示函数调用结果
disable_irq(irq); //中断不可用
enable_irq(irq); //使能中断,触发中断处理函数的执行
printk("out request_threaded_irq_init\n");
return 0;
}
模块退出函数调用:
static void __exit request_threaded_irq_exit(void)
{
free_irq(irq, NULL); //释放申请的中断
printk("Goodbye request_threaded_irq\n");
return;
}
模块加载、退出函数调用:
module_init(request_threaded_irq_init);
module_exit(request_threaded_irq_exit);
实例运行结果及分析:
编译模块,执行命令insmod request_threaded_irq.ko插入内核模块,然后输入命令dmesg -c查看内核输出信息,出现如图A
所示的结果。
在模块卸载之前输入命令cat /proc/interrupts查看文件/proc/interrupts的内容,出现如图B
所示的结果。
执行命令rmmod request_threaded_irq.ko卸载模块,模型卸载之后输入命令cat /proc/interrupts查看文件/proc/interrupts的内容,出现如图C
所示的结果。
结果分析:
由图A
可以看出函数request_threaded_irq( )的返回结果是0,说明动态申请中断成功,并且中断对应的处理函数及中断线程处理函数都被调度执行;图B
的显示结果同样也说明了函数request_threaded_irq( )动态申请中断成功,因为中断号11对应的中断信息出现在文件/proc/interrupts中,并且中断处理函数被调度执行了一次,正好也与图A
的输出信息互相吻合。图C
与图B
相对比可以判断在模块卸载之后,中断号是11的中断并没有被删除,只是删除了对应的设备,如果此时重新插入模块,也会成功,但是对应的中断处理函数不会被调用,执行命令cat /proc/interrupts输出结果同图B
一样。
酷客网相关文章:
评论前必须登录!
注册