Linux内核API request_threaded_irq

request_threaded_irq函数功能描述:函数request_threaded_irq( )首先对传入的参数进行正确性检查,根据传入的irq号获得数组irq_desc中以irq为下标的元素,然后动态地创建一个irqaction描述符,根据传入的参数初始化新生成的irqaction描述符,最后调用函数__setup_irq( )把该描述符加入到IRQ链表中,完成中断的动态申请及注册。

request_threaded_irq文件包含

#include<linux/interrupt.h>

request_threaded_irq函数定义

在内核源码中的位置: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 是对应的中断号,相应的取值是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。

request_threaded_irq返回参数说明

如果返回值是0则说明申请成功,如果申请不成功,则返回的值非零,一般为负数,可能的取值为-16、-38。例如,如果返回值是-16,则说明申请的中断号在内核中已被占用。

request_threaded_irq实例解析

编写测试文件: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所示的结果。

Linux内核API request_threaded_irq

在模块卸载之前输入命令cat /proc/interrupts查看文件/proc/interrupts的内容,出现如图B所示的结果。

Linux内核API request_threaded_irq

执行命令rmmod request_threaded_irq.ko卸载模块,模型卸载之后输入命令cat /proc/interrupts查看文件/proc/interrupts的内容,出现如图C所示的结果。

Linux内核API request_threaded_irq

结果分析:

由图A可以看出函数request_threaded_irq( )的返回结果是0,说明动态申请中断成功,并且中断对应的处理函数及中断线程处理函数都被调度执行;图B的显示结果同样也说明了函数request_threaded_irq( )动态申请中断成功,因为中断号11对应的中断信息出现在文件/proc/interrupts中,并且中断处理函数被调度执行了一次,正好也与图A的输出信息互相吻合。图C与图B相对比可以判断在模块卸载之后,中断号是11的中断并没有被删除,只是删除了对应的设备,如果此时重新插入模块,也会成功,但是对应的中断处理函数不会被调用,执行命令cat /proc/interrupts输出结果同图B一样。

赞(0)
未经允许不得转载:极客笔记 » Linux内核API request_threaded_irq
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址