Linux内核API remove_irq

remove_irq函数功能描述:此函数用于卸载IRQ链表中的与输入参数相对应的irqaction描述符。

功能实现过程:函数通过调用函数__free_irq( )实现其功能,传给__free_irq( )的参数是irq与act->dec_id,函数__free_irq( )根据参数irq找到数组irq_desc中对应的元素desc,如果不存在则返回NULL;如果存在则根据dev_id找到对应的irqaction标识符,如果不存在则返回NULL,如果存在则进行一定的操作,将其从IRQ链表中删除,最后返回该irqaction标识符。

remove_irq文件包含

#include<linux/irq.h>

remove_irq函数定义

在内核源码中的位置:linux-3.19.3/kernel/irq/manage.c

函数定义格式:

void remove_irq(unsigned int irq, struct irqaction *act)

remove_irq输入参数说明

参数unsigned int irq是对应的中断号,相应的取值是0~16640,系统已用的是0~31,其中编号IRQ9、IRQ10、IRQ15系统保留,32~16640是用于用户定义的中断。

参数act是与系统对应的一个irqaction标识符,是一个struct irqaction类型的结构体指针,其定义见文件linux-3.19.3/include/linux/interrupt.h,如下:

struct irqaction {
    irq_handler_t handler;
    void *dev_id;
    void __percpu *percpu_dev_id;
    struct irqaction *next;
    irq_handler_t thread_fn;
    struct task_struct *thread;
    unsigned int irq;
    unsigned int flags;
    unsigned long thread_flags;
    unsigned long thread_mask;
    const char *name;
    struct proc_dir_entry *dir;
} ____cacheline_internodealigned_in_smp;

其中:

  • 字段handler是一个函数指针,代表中断处理函数,此函数的返回值类型是irq_handler_t类型的变量,可能的取值是IRQ_NONE 、IRQ_HANDLED、IRQ_WAKE_THREAD。
  • 字段dev_id保存与此中断标识符相对应的设备标识符,用于识别设备。
  • 字段percpu_dev_id为设备识别符,用于识别设备。
  • 字段next指向中断向量链表中的下一个中断标识符。
  • 字段thread_fn是一个函数指针,指向中断线程处理函数,返回值类型与字段handler的返回值类型相同。
  • 字段thread是一个任务描述符指针,指向与此中断线程对应的线程。
  • 字段irq对应此中断标识符对应的中断号。
  • 字段f lags是用来标识中断的类型,其定义见文件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)
                                        // 复合定义
  • 字段thread_f lags是一个线程标志,标示一个线程所处的状态。
  • 字段thread_mask是对应的CPU掩码,表示此中断所在的CPU编号。
  • 字段name是与此中断标识符相对应的设备名。
  • 字段dir是一个目录入口指针,指向在文件夹/proc/irq中与此中断标识符所对应的中断号相对应的文件夹。

remove_irq返回参数说明

此函数不返回任何类型的数据。

remove_irq实例解析

编写测试文件:remove_irq.c

头文件引用及全局变量定义:

#include <linux/interrupt.h>
#include<linux/irq.h>
#include <linux/module.h>
MODULE_LICENSE("GPL");
static int irq=11;    //中断号定义

/*声明一个变量,中断号为10,中断处理函数是myhandler( ),中断的类型是IRQF_DISABLED类型的,
  中断对应的设备名是A_New_Device,设备编号是NULL(即设备不真实存在)*/
static struct irqaction act =
{
    .irq=11,
    .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);
    printk("in the interrupt handler function\n");
    return IRQ_NONE;
}

模块加载函数定义:

static int __init remove_irq_init(void)
{
    int result=0;
    struct irqaction *myact=&act;
    printk("into remove_irq_init\n");
    result=request_irq(myact->irq, myact->handler, myact->flags, myact-
>name, myact->dev_id);                                    //申请中断
    printk("the result is: %d\n", result);            //显示申请结果
    printk("out remove_irq_init\n");
    return 0;
}

模块退出函数定义:

static void __exit remove_irq_exit(void)
{
    printk("remove the irq in the remove_irq_exit function\n");
    remove_irq(irq, &act); //调用函数remove_irq( ), irq是对应的中断号,act是对应的中断变量
    printk("Goodbye remove_irq\n");
    return;
}

模块加载、退出函数调用:

module_init(remove_irq_init);
module_exit(remove_irq_exit);

实例运行结果及分析:

首先编译模块,执行命令insmod remove_irq.ko,然后先后输入命令dmesg -c查看内核输出信息,输入命令cat /proc/interrupts查看文件/proc/interrupts内容,会出现如图A所示的结果。

Linux内核API remove_irq

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

Linux内核API remove_irq

结果分析:

由图A可以判断中断申请成功,函数request_irq( )的返回结果和文件/proc/interrupts的内容都可以得出此结论;图B可以判断申请的中断被删除,从文件/proc/interrupts的内容可以看出虽然中断号11的记录还存在,但是对应的设备文件名为空,已经不是“A_New_Device”,说明函数remove_irq( )能够将与输入参数相关的中断从IRQ链表中删除。

Camera课程

Python教程

Java教程

Web教程

数据库教程

图形图像教程

办公软件教程

Linux教程

计算机教程

大数据教程

开发工具教程