当前位置: 首页 > article >正文

中断管理常用API(四)

一、request_irq(...)

          request_irq 函数主要用于硬中断相关操作,它的核心作用是把一个中断处理函数和特定的中断号进行绑定。当硬件设备触发该中断号对应的中断时,内核就会调用绑定的中断处理函数,像 irqhandler_func 这类。

        此函数在多种硬件设备驱动中都会被使用,不只是系统时钟(GP Timer)驱动。在驱动开发里,只要涉及到硬件中断处理,一般都会借助 request_irq 来注册中断处理函数。

其主要功能包含以下方面:

  1. 注册中断处理函数:把指定的中断处理函数与特定中断号关联起来,让内核在对应中断发生时能调用该处理函数。
  2. 中断资源管理:对中断资源进行管理,像检查中断号是否可用、将新申请的中断信息添加到内核的中断管理数据结构(例如 IRQ 链表)中。
  3. 中断标志处理:依据传入的中断标志参数(如 IRQF_DISABLEDIRQF_SHARED 等)对中断的行为进行配置。

        如果 request_irq 函数申请中断成功,会返回 0;若申请失败,则返回一个负的错误码,以此来表明具体的错误原因。

        具体内核源码设计如下:

参数irq对于中断号:

  • 取值是从 0--16640,系统已经使用的是 0-31,其中 IRQ9/10/15 系统保留;
  • 用户用于自定义中断:32--16640。

 

如request_irq(IRQ_LCDC_INT, lcdc_isr, IRQF_DISABLED, "LCDC", &lcdc);
什么时候才执行lcdc_isr, 呢?

         在 request_irq(IRQ_LCDC_INT, lcdc_isr, IRQF_DISABLED, "LCDC", &lcdc); 中,当中断号为 IRQ_LCDC_INT 的中断事件发生时,就会执行 lcdc_isr 中断处理函数。具体来说,当与之相关的硬件设备(这里是 LCDC 设备 )产生中断信号,且该中断信号被 CPU 检测和响应后,系统就会调用已注册的 lcdc_isr 函数来处理这个中断事件。

  • IRQF_DISABLED :表示中断处理程序是快速处理程序。当该标志位被设置,在调用此中断处理函数时,会屏蔽掉所有其他中断。这样做是为了确保当前中断处理能不受干扰地快速执行,适用于那些需要立即响应且处理过程不能被打断的紧急中断场景。比如一些关键硬件的状态变化中断,必须尽快处理且不能被其他中断干扰。
  • IRQF_SAMPLE_RANDOM :该中断可用于为系统提供随机数相关的熵源。系统在生成随机数时,会利用这类中断提供的信息,增加随机数的随机性和不确定性。
  • IRQF_SHARED :意味着多个设备可以共享同一个中断号。当设置此标志,多个设备可以共用一条中断线。在中断发生时,内核会循环调用该中断线上注册的所有中断处理函数,由每个函数自行判断是否是自己对应的设备产生的中断 。比如 PCI 总线上多个设备可能共享一个中断号。
  • IRQF_PROBE_SHARED :用于探测共享中断的情况。当调用者预期可能会出现共享中断的不匹配等情况时设置此标志,帮助系统更好地处理共享中断相关的探测和管理。
  • IRQF_TIMER :专用于时钟中断相关场景。时钟中断是系统中很重要的一种中断,用于维护系统时间、调度任务等,此标志明确该中断是用于时钟相关功能。
  • IRQF_PERCPU :表示该中断会在每个 CPU 周期执行。适用于一些需要在每个 CPU 上都单独进行处理的中断情况,比如某些与 CPU 本地状态或资源相关的中断处理。
  • IRQF_NOBALANCING :该标志表示此中断不参与中断负载均衡。在多 CPU 系统中,内核通常会尝试将中断负载均衡到各个 CPU 上,但设置此标志的中断不会参与这种均衡操作。
  • IRQF_IRQPOLL :在共享中断的场景下,用于根据注册时间等因素来判断中断处理顺序等相关操作,辅助管理共享中断的处理逻辑。
  • IRQF_ONESHOT :单次触发中断,即中断处理函数执行一次后,该中断就不再触发,除非再次进行相关设置或硬件重新产生触发条件。
  • IRQF_TRIGGER_NONE :表示无触发条件的中断,一般较少使用,更多是作为标志位组合等用途。
  • IRQF_TRIGGER_RISING :指定中断触发类型为上升沿有效,即当硬件信号从低电平变为高电平时,触发中断。
  • IRQF_TRIGGER_FALLING :指定中断触发类型为下降沿有效,即当硬件信号从高电平变为低电平时,触发中断。
  • IRQF_TRIGGER_HIGH :指定中断触发类型为高电平有效,只要硬件信号处于高电平状态,就会触发中断。
  • IRQF_TRIGGER_LOW :指定中断触发类型为低电平有效,只要硬件信号处于低电平状态,就会触发中断。
  • IRQF_TRIGGER_MASK :是上升沿、下降沿、高电平、低电平触发标志位的组合掩码,用于方便地对这几种触发类型标志位进行批量操作或判断 。
  • IRQF_TRIGGER_PROBE :用于触发式检测中断相关操作,帮助系统探测和管理中断触发条件等情况。

【代码案例】

requestirq.c

#include <linux/irq.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/slab.h>// 定义一个结构体来包含额外的参数
struct my_irq_data {int extra_param1;char *extra_param2;
};static int irq = 10; // 中断号
#define IRQF_DISABLED 0x00000020 // 中断禁止// 定义中断处理函数
static irqreturn_t irqhandler_func(int irq, void *dev_id) {struct my_irq_data *data = (struct my_irq_data *)dev_id;printk(KERN_INFO "调用自定义中断函数:irqhandler_func(...)函数.\n");printk(KERN_INFO "打印输出对应的中断号为:%d\n", irq);printk(KERN_INFO "额外参数1的值为:%d\n", data->extra_param1);printk(KERN_INFO "额外参数2的值为:%s\n", data->extra_param2);printk(KERN_INFO "退出自定义中断函数:irqhandler_func(...)函数.\n");return IRQ_NONE;
}static struct my_irq_data *my_data;static int __init setupirq_initfunc(void) {int rst = 0;printk(KERN_INFO "调用内核初始化模块函数:setupirq_initfunc(...)函数.\n");// 分配内存给结构体my_data = kmalloc(sizeof(struct my_irq_data), GFP_KERNEL);if (!my_data) {printk(KERN_ERR "内存分配失败\n");return -ENOMEM;}// 初始化额外的参数my_data->extra_param1 = 42;my_data->extra_param2 = "Hello, World!";// 调用 request_irq 申请中断rst = request_irq(irq, irqhandler_func, IRQF_DISABLED, "Test_New_Device", my_data);if (rst < 0) {printk(KERN_ERR "申请中断失败,错误码:%d\n", rst);kfree(my_data);return rst;}printk(KERN_INFO "打印输出中断申请结果:成功\n");printk(KERN_INFO "退出内核初始化模块函数:setupirq_initfunc(...)函数.\n");return 0;
}static void __exit setupirq_exitfunc(void) {printk(KERN_INFO "正常退出内核:开始释放中断资源.\n");// 调用 free_irq 释放中断free_irq(irq, my_data);// 释放分配的内存kfree(my_data);printk(KERN_INFO "调用 free_irq 删除申请的中断成功,内存释放完成.\n");
}MODULE_LICENSE("GPL");
module_init(setupirq_initfunc);
module_exit(setupirq_exitfunc);

Makefile

#!/bin/bashccflags_y += -O2ifneq ($(KERNELRELEASE),)
obj-m := requestirq.o
else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)default:$(MAKE) -C $(KERNELDIR) M=$(PWD) modules 
endifclean:rm -rf *.o *.ko *.mod.cdepend .depend dep:$(CC)  -M *.c > .depend 

编译插入卸载

 

二、request_threaded_irq(...)

        该函数主要功能是根据传递的参数进行正确定检查,然后动态创建一个irqaction描述符且初始化,最后调用相关API将此描述符加入到IRQ链表中,完成中断动态申请以及注册。具体Linux内核源码设计如下:

  • 参数 irq:中断号
  • 参数 handler:中断处理函数
  • 参数 thread_fn:中断线程处理函数
  • 参数 irqflags:中断标识符
  • 参数 devname:中断对应的设备名称
  • 参数 dev_id:设备描述符指针
  • 此函数返回值:返回类型为 irq_handler_t,返回值为 0 证明申请成功,申请失败返回值非零

request_irq 和 request_threaded_irq 都是 Linux 内核中用于申请中断的函数 ,二者主要区别如下:

1. 函数参数

  • request_irq:原型为 int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, const char *name, void *dev) 。参数包括中断号 irq 、中断处理函数 handler 、中断标志 flags 、中断名字 name 、设备区分参数 dev 。
  • request_threaded_irq:原型为 int request_threaded_irq(unsigned int irq, irq_handler_t handler, irq_handler_t thread_fn, unsigned long flags, const char *name, void *dev) 。相比 request_irq ,多了一个 thread_fn 参数,该参数是在线程中运行的函数。

2. 中断处理方式

  • request_irq:中断处理函数 handler 在中断上下文执行,该上下文不可抢占。若中断处理函数执行时间长,会阻塞其他中断和任务,影响系统实时性。
  • request_threaded_irq:将中断处理分为两部分。 handler 作为快速的硬件中断处理程序,在中断发生时快速响应,执行确认中断源、禁用中断源等必要硬件操作; thread_fn 作为线程中断处理程序,在独立的线程上下文运行,可被抢占,适合执行耗时操作 。比如网络数据包处理场景,可把耗时逻辑放 thread_fn 中,减少中断上下文执行时间。

3. 执行效率与适用场景

  • request_irq:适用于中断处理简单、耗时短的场景。如果处理过程不复杂,能快速执行完,用 request_irq 可简单高效处理中断。
  • request_threaded_irq:适用于中断处理有耗时操作的场景。在实时或嵌入式系统中,对实时性要求高,通过线程化中断处理,可提高系统实时性能和响应性 。 多 CPU 系统中,多个中断的内核线程可分配到不同 CPU 执行,提高整体处理效率。

4. 本质关系

request_irq 本质上是 request_threaded_irq 的封装,相当于调用 request_threaded_irq 时将 thread_fn 参数置为 NULL 。

 【代码案例】

requestthreadedirq.c

#include <linux/irq.h>
#include <linux/module.h>
#include <linux/interrupt.h>static int irq = 11; // 中断号
#define IRQF_DISABLED 0x00000020 /*中断禁止*/// 自定义中断处理函数
static irqreturn_t irqhandler_func(int irq,void *dev_id){printk("打印输出中断处理函数data所对应的中断号为:%d\n",irq);return IRQ_WAKE_THREAD; // 触发中断线程函数执行
}// 自定义中断线程处理函数
static irqreturn_t irqthread_func(int irq,void *dev_id){printk("打印输出中断线程处理函数data所对应的中断号为:%d\n",irq);return IRQ_HANDLED;
}static int __init requestthreadedirq_initfunc(void){int rst=0;printk("调用内核模块函数:requestthreadedirq_initfunc(...).\n");rst = request_threaded_irq(irq,irqhandler_func,irqthread_func,IRQF_DISABLED,"Test_New_Device",NULL);printk("打印输出调用request_threaded_irq(...)函数返回的rst值为:%d\n",rst);disable_irq(irq);enable_irq(irq); printk("退出内核模块函数:requestthreadedirq_initfunc(...).\n");return 0;
}static void requestthreadedirq_voidfunc(void){free_irq(irq,NULL); // 释放申请的中断处理printk("内核正常退出:request_threaded_irq(...)函数.\n");
}MODULE_LICENSE("GPL");module_init(requestthreadedirq_initfunc);
module_exit(requestthreadedirq_voidfunc);

Makefile

#!/bin/bashccflags_y += -O2ifneq ($(KERNELRELEASE),)
obj-m := requestthreadedirq.o
else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)default:$(MAKE) -C $(KERNELDIR) M=$(PWD) modules 
endifclean:rm -rf *.o *.ko *.mod.cdepend .depend dep:$(CC)  -M *.c > .depend 

编译插入卸载

 https://github.com/0voice

相关文章:

中断管理常用API(四)

一、request_irq(...) request_irq 函数主要用于硬中断相关操作&#xff0c;它的核心作用是把一个中断处理函数和特定的中断号进行绑定。当硬件设备触发该中断号对应的中断时&#xff0c;内核就会调用绑定的中断处理函数&#xff0c;像 irqhandler_func 这类。 此函数在多种硬件…...

RabbitMQ高级特性--重试特性

目录 1.重试配置 2.配置交换机&队列 3.发送消息 4.消费消息 5. 运行程序观察结果 6. 手动确认 注意&#xff1a; 在消息传递过程中, 可能会遇到各种问题, 如网络故障, 服务不可用, 资源不足等, 这些问题可能导致消息处理失败. 为了解决这些问题, RabbitMQ 提供了重试机制, …...

pyspark学习rdd处理数据方法——学习记录

python黑马程序员 """ 文件&#xff0c;按JSON字符串存储 1. 城市按销售额排名 2. 全部城市有哪些商品类别在售卖 3. 上海市有哪些商品类别在售卖 """ from pyspark import SparkConf, SparkContext import os import jsonos.environ[PYSPARK_P…...

C语言入门教程100讲(0)从了解C语言的发展史开始

文章目录 引言1. C语言的起源2. C语言的诞生3. C语言的标准化4. C语言的进一步发展5. C语言的影响与应用6. C语言的未来结语引言 C语言作为一种高效、灵活且具有广泛应用的编程语言,在计算机科学史上占据着举足轻重的地位。它的设计不仅影响了后来的编程语言,也对操作系统、…...

【HTML 基础教程】HTML <head>

HTML <head> 查看在线实例 - 定义了HTML文档的标题"><title> - 定义了HTML文档的标题 使用 <title> 标签定义HTML文档的标题 - 定义了所有链接的URL"><base> - 定义了所有链接的URL 使用 <base> 定义页面中所有链接默认的链接目…...

练习题:111

目录 Python题目 题目 题目分析 需求理解 关键知识点 实现思路分析 代码实现 代码解释 指定文件路径和名称&#xff1a; 定义要写入的内容&#xff1a; 打开文件并写入内容&#xff1a; 异常处理&#xff1a; 输出提示信息&#xff1a; 运行思路 结束语 Python题…...

混合知识表示系统框架python示例

前文我们已经深入学习了框架表示法、产生式规则和一阶谓词逻辑,并对它们进行了深度对比,发现它们在不同的应用场景下各有优缺点。 一阶谓词逻辑适合复杂逻辑推理场景,具有数学定理证明、形式化系统规范的优点;产生式规则适合动态决策系统,支持实时决策(如风控、诊断),规…...

信号集操作函数

目录 一、sigpending函数 功能&#xff1a; 头文件&#xff1a; 函数原型&#xff1a; 函数参数&#xff1a; 返回值&#xff1a; 二、sigemptyset函数 功能&#xff1a; 原型&#xff1a; 参数&#xff1a; 返回值&#xff1a; 三、sigfillset函数 功能&#xf…...

学习不同电脑cpu分类及选购指南

关于电脑cpu 一、CPU型号的核心组成与命名规则Intel命名规则:AMD命名规则:5. 后缀:Intel常见后缀及其含义:AMD后缀一些常见的后缀及其含义:二、主流品牌CPU的分类与性能差异三、区分CPU型号的实用方法四、主流品牌CPU对比与选择建议五、选购CPU的注意事项关于不同主流CPU的…...

MATLAB 控制系统设计与仿真 - 30

用极点配置设计伺服系统 方法2-反馈修正 如果我们想只用前馈校正输入&#xff0c;从而达到伺服控制的效果&#xff0c;我们需要很精确的知道系统的参数模型&#xff0c;否则系统输出仍然具有较大的静态误差。 但是如果我们在误差比较器和系统的前馈通道之间插入一个积分器&a…...

Baklib知识中台驱动智能架构升级

构建四库体系驱动架构升级 在数字化转型过程中&#xff0c;企业普遍面临知识资源分散、隐性经验难以沉淀的痛点。Baklib通过构建知识库、案例库、流程库及资源库四层核心体系&#xff0c;为知识中台搭建起结构化基础框架。知识库以AI分类引擎实现文档标签化存储&#xff0c;案…...

IP第一次笔记

一、TCP协议 第0步&#xff1a;如果浏览器和host文件存在域名对应的P地址记录关系 则直接封装HTTP数据报文&#xff0c;如果没有记录则触发DNS解析获 取目标域名对应的P地址 第一步&#xff1a;终端主机想服务器发起TCP三次握手 1.TCP的三次握手 2.传输网页数据 HTTP --应用层…...

计算机三级信息安全部分英文缩写

eip&#xff0c;指令寄存器&#xff0c;用于存放指向下一条将执行指令的指针&#xff0c;即返回地址栈顶指针esp基址指针寄存器EBP&#xff0c;基地址数据执行保护DEP(Data Execute Prevention)技术可以设置内存堆栈区的代码为不可执行状态&#xff0c;从而防范溢出后代码的执行…...

Supplements of My Research Proposal: My Perspectives on the RAG

To build an agent, I think there’re a lot of things that can be considered from humans. For example, how do self-learners learn things? I think 2 sources of knowledge can never be ignored: textbooks and online cources. A question then arise: how do we …...

【安全】nginx防止host头攻击

host攻击 系统上线之前要经过安全测试,安全测试中有这么一项,请求头中的host字段,这个值随便修改之后,响应还可以正常返回,这种这种就是有风险的,是测试不通过的,默认情况下,浏览器地址栏中的URL和请求头中的host字段值的ip和端口&#xff08;或者是域名&#xff09;是一样的&a…...

vue3实现router路由

说明&#xff1a; vue3实现router路由 效果图&#xff1a; step1:项目结构 src/ ├── views/ │ ├── Home.vue │ └── User.vue ├── router/ │ └── index.js ├── App.vue └── main.jsstep2:左边路由列表C:\Users\wangrusheng\PycharmProjects\un…...

蓝桥杯省赛 棋盘 3533 二维差分+二维前缀和

传送门 0棋盘 - 蓝桥云课 const int N 2e3 10;int n,m; int a[N][N];void insert(int x11,int y11,int x22,int y22) {a[x11][y11] ;a[x11][y22 1] --;a[x22 1][y11] --;a[x22 1][y22 1] ; }void solve() {cin >> n >> m;for (int i 1;i < m;i ){int x11…...

1500 字节 MTU | 溯源 / 技术权衡 / 应用影响

注&#xff1a;本文为 “MTU 字节” 相关文章合辑。 机翻&#xff0c;未校。 讨论部分&#xff0c;以提交人为分界。 单行只有阿拉伯数字的&#xff0c;为引文转译时对回复的点赞数。 How 1500 bytes became the MTU of the internet 1500 字节是如何成为互联网 MTU 的 Fe…...

智能仪表板DevExpress Dashboard v24.2新版亮点:支持.NET 9

使用DevExpress BI Dashboard&#xff0c;再选择合适的UI元素&#xff08;图表、数据透视表、数据卡、计量器、地图和网格&#xff09;&#xff0c;删除相应参数、值和序列的数据字段&#xff0c;就可以轻松地为执行主管和商业用户创建有洞察力、信息丰富的、跨平台和设备的决策…...

【数据结构】二叉树的递归

数据结构系列三&#xff1a;二叉树(二) 一、递归的原理 1.全访问 2.主角 3.返回值 4.执等 二、递归的化关系思路 三、递归的方法设计 一、递归的原理 1.全访问 方法里调用方法自己&#xff0c;就会形成调用方法本身的一层一层全新相同的调用&#xff0c;方法的形参设置…...

Optional的stream方法,flatMap, filter应用

Java 8引入的Optional和Stream彻底改变了我们处理空值和集合操作的方式。本文将深入探讨如何将二者结合使用&#xff0c;通过四个核心场景提升代码的健壮性和简洁性。 一、Optional构成的Stream&#xff1a;空值自动过滤 当处理Optional集合时&#xff0c;我们常需要过滤掉空…...

Intellij ider部署python项目教程

自己写了一个python项目【mac电脑】&#xff0c;然后用Intellij ider打开&#xff0c;配置python解释器&#xff0c;然后一运行&#xff0c;一直报错&#xff0c; If this fails your Python may not be configured for Tk ModuleNotFoundError: No module named _tkinter 各…...

Linux进程状态补充(10)

文章目录 前言一、阻塞二、挂起三、运行R四、休眠D五、四个重要概念总结 前言 上篇内容大家看的云里雾里&#xff0c;这实在是正常不过&#xff0c;因为例如 写实拷贝 等一些概念的深层原理我还没有讲解&#xff0c;大家不用紧张&#xff0c;我们继续往下学习就行&#xff01;&…...

使用ANTLR4解析Yaml,JSON和Latex

文章目录 ANTLR4基本使用**1. 安装 Java 运行时&#xff08;必需&#xff09;****2. 安装 ANTLR4 命令行工具****方法一&#xff1a;通过包管理器&#xff08;推荐&#xff09;****macOS/Linux (Homebrew)****Windows (Chocolatey)** **方法二&#xff1a;手动安装&#xff08;…...

基于Python深度学习的鲨鱼识别分类系统

摘要&#xff1a;鲨鱼是海洋环境健康的指标&#xff0c;但受到过度捕捞和数据缺乏的挑战。传统的观察方法成本高昂且难以收集数据&#xff0c;特别是对于具有较大活动范围的物种。论文讨论了如何利用基于媒体的远程监测方法&#xff0c;结合机器学习和自动化技术&#xff0c;来…...

Ruby 简介

Ruby 简介 引言 Ruby 是一种广泛使用的动态、开源的编程语言,自 1995 年由日本程序员 Yukihiro Matsumoto(通称 Matz)设计以来,它以其优雅的语法、强大的库支持和跨平台特性赢得了全球开发者的青睐。本文将详细介绍 Ruby 的起源、特点、应用领域以及它在现代软件开发中的…...

EtherNet/IP转ProfiNet协议转换网关驱动西门子PLC与流量计的毫秒级压力同步控制

一、案例背景 汽车涂装线的静电喷涂工艺对压缩空气流量稳定性要求极高。原系统中Alicat流量计与西门子PLC因协议差异无法联动&#xff0c;导致涂料浪费率高达8%。通过JM-EIPM-PN网关实现供气系统与PLC的深度集成。从而实现了EtherNet/IP转ProfiNet的通讯。 二、设备连接与配置…...

为mariadb和mysql添加用户和修改密码的方法

一、查看MariaDB中的用户 步骤1&#xff1a;登录MariaDB sudo mysql -u root -p # 使用root账户登录&#xff08;输入密码&#xff09; 步骤2&#xff1a;查询用户列表 -- 切换到mysql系统数据库 USE mysql; -- 查看所有用户及其主机权限 SELECT User, Host FROM user; 输出…...

【力扣刷题|第十七天】0-1 背包 完全背包

目标和 力扣题目网址:目标和 这道题我们先用回溯的思想来做。首先我们设正数和为S&#xff0c;数组和为N&#xff0c;目标值为T&#xff0c;那么S-(N-S)T化简之后可以得S(TN)/2即选择的正数个数为偶数&#xff0c;而且NT也为偶数&#xff0c;那么第一个判断条件我们就有了&…...

python的内存管理

目录 1. 引用计数 2. 垃圾收集&#xff08;GC&#xff09; python的内存管理主要是引用计数和垃圾回收器来进行内存管理 1. 引用计数 每个 Python 对象都有一个引用计数&#xff0c;当引用计数为零时&#xff0c;对象的内存会被释放。 import sysa [] # 创建一个空列表对…...