linux内核中断

news2024/11/18 9:28:46

目录

硬中断特点

中断API

线程中断

系统标准的优先级顺序

中断信息查看

中断上半部与下半部

软中断与并发


硬中断特点

  • 优先级最高
  • 中断函数在中断上下文中,不能阻塞

        不要间接或直接调用shedule()

        在申请内存空间时,使用GFP_ATOMIC 标志(非阻塞,尽可能快);

        不能在用户与内核空间传递数据

  • 中断屏蔽:

        默认情况下,在中断函数处理时,所有的本地CPU的中断是被屏蔽的

  • 尽可能的快

        几十微妙内,如果超过则使用中断下半部

下面这块程序存在的问题

my_interrupt()
{
	struct mys *sp;
	ack_intr();
	x = read_regX();
	sp = kzalloc(SIZE_HWBUF, GFP_KERNEL);
	if (!sp)
		return -ENOMEM;
	sp = fetch_data_from_hw();
	copy_to_user(ubuf, sp, count);
	kfree(sp);
}
  1. kzalloc() 使用GFP_KERNEL标志,可能引起调用schedule(),内核会输出oops错误;
  2. copy_to_user()调用可能会引起页错误,引起上下文切换,触发schedule()
  3. 更一般的错误,a函数最终调用了schedule(),将会引起oops错误。a()--b()--c()--[] --g() --schedule()--[]

中断API

request_irq()
devm_request_irq()


*free_irq(unsigned int, void *);

详细分析request_irq函数的参数 

#include <linux/interrupt.h>
int __must_check
request_irq(unsigned int irq, irq_handler_t (*handler_func)(int, void *),
unsigned long flags, const char *name, void *dev);
  • 头文件 #include <linux/interrupt.h>
  • irq:中断线
  • irq_handler_t:中断处理函数
  • flag:中断标志bitmask,中断标志在下节介绍
  • name:驱动名
  • *dev:给中断函数传递参数

中断标志

  • IRQF_SHARED:在几个设备中间允许共享IRQ线
  • IRQF_ONESHOT:经常用在线程中断中,以确保IRQ在线程处理程序完成之前保持禁用状态;
  • __IRQF_TIMER:定时器中断 ,定时器中断标志组合如下

#define IRQF_TIMER(__IRQF_TIMER | IRQF_NO_SUSPEND | IRQF_NO_THREAD)

触发方式

  • Level-triggered:中断在没有得到响应之前,一直触发。
  • Edge-triggered:中断仅仅触发一次

中断掩码

        芯片的中断控制器(PIC/GIC)有掩码寄存器,操作系统能够通过编程屏蔽或阻塞硬件中断。

  1. 尽可能的保持中断使能,这对于系统至关重要。如果中断被阻塞,外设不能响应,系统性能滞后或许受此影响。使用自旋锁锁定将导致中断和抢占被禁用。
  2. Linux系统的默认行为,发生硬件中断且该中断未被屏蔽时,内核确保在其中断(hardirq)处理程序执行时,本地CPU内核上执行处理程序的所有中断都被禁用。
  3. 多核系统上的中断:当IRQn在CPU内核1上执行时,除内核1外,其他中断在所有CPU内核上保持启用。因此,在多核系统硬件上,中断可以在不同的CPU内核上并行运行。就全局数据而言,只要他们互不干涉,这就没问题!如果有竞争,就必须使用锁定。 

线程中断

//线程中断
request_threaded_irq()
devm_request_threaded_irq() (recommended!)

内核线程与用户模式线程非常相似,它在进程上下文中独立运行,并有自己的任务结构,能够被调度。

  • 实现正在的实时
  • 消除软中断的瓶颈:

消除的瓶颈如何理解?

  • 线程中断运行在进程上下文中,,它被认为不像hardirq处理程序那样重要;因此,中断处理可能需要更长的时间。
  • 当硬中断执行时,中断IRQ line 在所有核上都禁止。如果执行到完成需要一段时间,那么系统的响应可能会显著下降;而线程处理程序执行时,默认启用硬件IRQ line。这有助于提高性能和响应能力。

线程处理程序的限制

  • IRQF_ONESHOT 必须要存在
  • 在处理NIC,多媒体等时处理速度会很慢,建议使用top/bottom机制

系统标准的优先级顺序

  • 硬件中断 (抢占了一切资源)
  • 实时线程(SCHED_FIFO.  SCHED_RR)
  • 处理器异常(系统调用,缺页异常等)
  • 用户模式线程(SCHED_OTHER)

如何判定选择硬中断还是线程中断?

内核提供了request_any_context_irq,根据特定情况,它将把中断处理程序设置为hardirq处理程序或线程处理程序。

int __must_check
request_any_context_irq(unsigned int irq, irq_handler_t handler,
unsigned long flags, const char *name, void *dev_id);

返回值

  •         如果运行在硬中断上下文,返回IRQC_IS_HARDIRQ;
  •         如果运行在进程或线程环境中,返回IRQC_IS_NESTED;
  •         返回负数,代表执行错误 

中断信息查看

查看硬中断

# cat /proc/interrupts 
            CPU0       CPU1       CPU2       CPU3       
   0:         24          0          0          0   IO-APIC    2-edge      timer
   1:      15354       5040      12673       1046   IO-APIC    1-edge      i8042
   8:          0          1          0          0   IO-APIC    8-edge      rtc0
   9:          0          0          0          0   IO-APIC    9-fasteoi   acpi
  12:          0      58896      51200      29989   IO-APIC   12-edge      i8042
  14:          0          0          0          0   IO-APIC   14-edge      ata_piix
  15:          0          0          0          0   IO-APIC   15-edge      ata_piix
  16:          0     122949          0        289   IO-APIC   16-fasteoi   vmwgfx, snd_ens1371
  17:      37934          0          0          0   IO-APIC   17-fasteoi   ehci_hcd:usb1, ioc0
  18:          0         41          0          0   IO-APIC   18-fasteoi   uhci_hcd:usb2
  19:          0          0         67      31218   IO-APIC   19-fasteoi   ens33

查看软中断 

# cat /proc/softirqs 
                    CPU0       CPU1       CPU2       CPU3       
          HI:          0          0          0          0
       TIMER:       8700       9001       8961      10715
      NET_TX:         12          3          2          2
      NET_RX:         76          7          7          3
       BLOCK:       2642          0          0          0
    IRQ_POLL:          0          0          0          0
     TASKLET:          0          0          1          0
       SCHED:       5516       4294       3979       3572
     HRTIMER:          0          0          0          0
         RCU:       6481       7745       9292       7009

使用线程中断处理是现代的一种方式,使用下半部机制是传统的方法。

中断上半部与下半部

中断上半部处理比较快的程序,如执行纯粹小的需求,中断处于关闭状态;

下半部处理相对较慢的处理程序,也是大部分中断工作;中断使能状态;

上半部的函数有:

                request_irq() / devm_request_irq() / request_threaded_irq() /
devm_request_threaded_irq()

下半部的函数:

                tasklet,workqueue,softirq

下半部分仍然在原子或中断上下文中运行!

  • 不能传输数据(用户和内核空间);
  • 分配内存要使用GFP_ATOMIC;
  • 不能直接间接调用schedule();

tasklet

#include <linux/interrupt.h>
void tasklet_init(struct tasklet_struct *t, void (*func)(unsigned long),
unsigned long data);
void tasklet_schedule(struct tasklet_struct *t);


/ * 下半部的处理 */
static void mydrv_tasklet(unsigned long data)
{

	process_it(); // 中断的绝大多数处理
}
/*上半部处理 */
static irqreturn_t my_hardirq_handler(int irq, void *data)
{
	tasklet_schedule(ts);//调度tasklet执行
	return IRQ_HANDLED;
}


static struct tasklet_struct *ts;

static int __init mydriver_init(void)
{
	struct device *dev;

	/* misc设备注册*/	
	ret = misc_register(&keylog_miscdev);
	dev = keylog_miscdev.this_device;
	//申请内存
	ts = devm_kzalloc(dev, sizeof(struct tasklet_struct), GFP_KERNEL);

	//tasklet初始化,并注册回调函数
	tasklet_init(ts, mydrv_tasklet, 0);

	//申请中断 中断处理函数my_hardirq_handler
	ret = devm_request_irq(dev, MYDRV_IRQ, my_hardirq_handler,
				IRQF_SHARED, OURMODNAME, THIS_MODULE);
}

tasklet_hi_schedule()相比tasklet_schedule()有更高的软中断优先级。

softirq

// kernel/softirq.c
void open_softirq(int nr, void (*action)(struct softirq_action *))
{
    softirq_vec[nr].action = action;
}

软中断类型以及解释

优先级序号Softirq说明函数
0HI_SOFTIRQ最高的软件优先级tasklet_hi_action()
1TIMER_SOFTIRQ定时器run_timer_softirq()
2NET_TX_SOFTIRQ网络栈发送net_tx_action()
3NET_RX_SOFTIRQ网络栈接收net_rx_action()
4BLOCK_SOFTIRQBlock进程blk_done_softirq()
5IRQ_POLL_SOFTIRQ内核的块层轮询IRQ模式irq_poll_softirq()
6TASKLET_SOFTIRQtasklet下半部tasklet_action()
7SCHED_SOFTIRQCFS调度;将任务迁移到其他队列run_rebalance_domains()
8HRTIMER_SOFTIRQ高精度定时器hrtimer_run_softrq()
9RCU_SOFTIRQ执行RCU进程

rcu_core_si()/

rcu_process_callbacks()

软中断与并发

  • tasklet 不能并发执行;softirq可以并发执行,因此需要锁;
  • 软中断能被硬中断打断;
  • 软中断不能抢占正在执行的软中断,虽然有更优的优先级,必须安装优先级使用;
  • spin_lock_bh(),当被锁住的时候,禁止软中断;防止死锁

硬中断,tasklet与线程处理函数的比较

时间使用优缺点
<=10微妙hardirq最佳方案
[10,100]微妙hardirq或hardirq与tasklet(softirq)运行压力测试/工作负载,看看是否真的需要tasklet。对于线程处理程序或工作队列,不鼓励使用
100毫秒,非关键的设备hardirq,threaded handler, workqueue避免softirq处理,这有助于减少系统延迟,但可能导致处理速度稍慢
100毫秒,关键设备(网络、块、媒体设备)hardirq,tasklet当大量中断到来时,可能会导致“livelock”问题和长时间的延迟
100毫秒,极其关键的工作或设备hardirq,hi-tasklet,softirq相当极端,不太可能情况

大量未执行的softirq可能导致livelock的情况,以下两种方式缓解了这个问题

  • 线程中断或工作队列
  • 调用ksoftirqd/n内核线程来接管softirq处理

上述的两个例子运行在进程上下文,缓解了线程不足的问题。

如何知道程序处在进程或中断上下文中? 内核源码中有函数

// include/linux/preempt.h
/*
* Are we doing bottom half or hardware interrupt processing?
*
* in_irq() - We're in (hard) IRQ context
* in_softirq() - We have BH disabled, or are processing softirqs
* in_interrupt() - We're in NMI,IRQ,SoftIRQ context or have BH disabled
* in_serving_softirq() - We're in softirq context
* in_nmi() - We're in NMI context
* in_task() - We're in task context

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/112997.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Blender——苹果纹理绘制

效果图 前言 在进行纹理绘制之前&#xff0c;首先要具有苹果三维模型。 关于苹果的建模请参考&#xff1a;Blender——“苹果”建模_行秋的博客 1.苹果UV的展开 1.1首先点击UV Eidting&#xff0c;滑动三维模型&#xff0c;使其大小适中。 1.2打开左上角的UV选区同步&#x…

IPv6 的地址(计算机网络-网络层)

目录 IPv6地址的表示方法 IPv6的分类 IPv6 全球单播地址 IPv6 多播地址 IPv6地址的表示方法 在 IPv6 中&#xff0c;每个地址占 128 位&#xff0c;地址空间大于 3.4 *10^ 38 。在想象得到的将来&#xff0c;IPv6的地址空间是不可能用完的 128位的IPv6地址使用冒号十六进制记…

玩以太坊链上项目的必备技能(库 [library]-Solidity之旅十七)

库&#xff08;library&#xff09; 作为开发者的您&#xff0c;想必对项目中重复使用的工具函数&#xff0c;抽取到一个公共中&#xff0c;以便可以在您项目中的其它位置可调用。 而 Solidity 与您所熟知的没有什么不同&#xff0c;它也是用来实现可重复调用&#xff0c;且还…

基于 Traefik 的激进 TLS 安全配置实践

前言 Traefik是一个现代的HTTP反向代理和负载均衡器&#xff0c;使部署微服务变得容易。 Traefik可以与现有的多种基础设施组件&#xff08;Docker、Swarm模式、Kubernetes、Marathon、Consul、Etcd、Rancher、Amazon ECS...&#xff09;集成&#xff0c;并自动和动态地配置自…

力扣(39.40)补9.20

目前打算刷些算法题&#xff0c;数据结构的题暂时放一放吧。 39.组合总和 不会&#xff0c;毕竟好久没做回溯了。 看了这个图会好理解很多呦。 class Solution { List<List<Integer>> ansnew ArrayList<>(); List<Integer> listnew ArrayList<>(…

AcWing算法学习之动态规划(基础)

背包问题 01背包问题 思路&#xff1a; 01背包问题&#xff0c;表示每个物品要么放&#xff0c;要么不放。从集合的角度分析DP问题&#xff0c;状态表示为&#xff1a;选择前i个物品&#xff0c;总体积小于等于j的选法的集合&#xff0c;属性f[i][j]表示价值的最大值。状态计算…

正交编码器数字滤波器(二)

正交编码器数字滤波器&#xff08;一&#xff09;电路初画完了&#xff0c;正交编码器数字滤波器&#xff08;二&#xff09;把核心部分用HDL描述语言实现了&#xff0c;放在一个小芯片里。 上面的整张图上&#xff0c;截出下面的小图&#xff0c;就用古老的ABEL工具实现它。 这…

高斯函数和C++简单实现

高斯函数在科学和工程中有广泛应用&#xff1b;其定义为&#xff0c; 其一般图像为&#xff0c; 高斯函数的图形在形状上像一个倒悬着的钟&#xff1b;参数a指高斯曲线的峰值&#xff0c;b为其对应的横坐标&#xff0c;c即标准差&#xff08;有时也叫高斯RMS宽值&#xff09;&a…

【1754. 构造字典序最大的合并字符串】

来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 描述&#xff1a; 给你两个字符串 word1 和 word2 。你需要按下述方式构造一个新字符串 merge &#xff1a;如果 word1 或 word2 非空&#xff0c;选择 下面选项之一 继续操作&#xff1a; 如果 word1 非空&#xff0…

Python常用基础语法知识点大全

介绍 Python 是一门独特的语言&#xff0c;快速浏览一下他的要点&#xff1a; 面向对象&#xff1a;每一个变量都是一个类&#xff0c;有其自己的属性&#xff08;attribute&#xff09;与方法&#xff08;method&#xff09;。语法块&#xff1a;用缩进&#xff08;四个空格…

Qml 中用 Shader 实现圣诞树旋转灯

一、前言 2022年圣诞节到来啦&#xff0c;很高兴这次我们又能一起度过~ 这次给大家带来一个简单漂亮圣诞树灯。 当然了&#xff0c;本篇文章主要是讲解一下如何在 Qml 中使用 GLSL 来实现自己的特效。 至于代码嘛&#xff0c;我比较喜欢在 Shaderjoy 上寻找&#xff0c;那里有很…

Biotin-PEG-Biotin,生物素-聚乙二醇-生物素聚乙二醇试剂供应

一&#xff1a;产品描述 1、名称 英文&#xff1a;Biotin-PEG-Biotin 中文&#xff1a;生物素-聚乙二醇-生物素 2、CAS编号&#xff1a;N/A 3、所属分类&#xff1a;Biotin PEG 4、分子量&#xff1a;可定制&#xff0c;2000/10000/3400/1000/20000/500 5、质量控制&…

c++继承知识点

目录1.继承的概念及定义1.1继承的概念1.2 继承定义1.2.1定义格式1.2.2继承关系和访问限定符1.2.3继承基类成员访问方式的变化2.基类和派生类对象赋值转换3.继承中的作用域4.派生类的默认成员函数5.继承与友元6. 继承与静态成员如何定义一个不被继承的类7.继承的一个题目8. 复杂…

目标检测之YOLOv2算法分析

要点 Batch Normalization 训练 若batchsize64,某一层的某一个神经元会输出64个响应值&#xff0c;对这64个响应值求均值&#xff0c;标准差&#xff0c;然后标准化&#xff0c;对标准化的结果乘λβ\lambda \betaλβ,其中λ\lambdaλ和 β\betaβ是需要训练的参数&#xf…

Windows平台RTMP、RTSP播放器录像模块精细化控制

技术背景 上篇文章&#xff0c;我们介绍了Unity平台RTMP、RTSP播放器录像功能&#xff0c;这里&#xff0c;我们详细的介绍下&#xff0c;做个RTSP或RTMP拉流端录像模块有哪些需要考虑的技术点&#xff1f; 在我们常规的考量&#xff0c;RTMP或RTSP流录制&#xff0c;无非就是…

在gitee上新建仓库并上传文件

一、进入到自己gitee的个人主页&#xff0c;点击图示新建仓库 二、根据图示操作&#xff0c;最后点击创建 三、如果没有配置git全局设置&#xff0c;需要配置一下(配置过的可以跳过这一步) 四、打开你要上传的文件&#xff0c;在里面右击鼠标&#xff0c;点击如图所示 五、输入…

spring之Bean的循环依赖问题

文章目录一、Bean的循环依赖之Set注入模式下1、Husband类2、Wife类3、Spring配置文件4、测试类5、测试结果6、结论二、Bean的循环依赖之构造方法注入模式下1、Husband类2、Wife类3、Spring配置文件4、测试类5、运行结果三、Spring解决循环依赖的机理三级缓存&#xff08;面试常…

PyQt5 基本布局管理 及 信号槽机制

一&#xff1a;布局设计 & 信号槽机制 效果实现如下&#xff1a; 对于窗口整体设计左右布局 对于左边布局&#xff0c;包括有水平布局(用户信息 左上方一块)垂直布局(多个按钮 左下方一块) 对于右边布局&#xff0c;主要是窗口切换&#xff0c;通过按下左边布局的左下方侧按…

SQLAlchemy连接MySQL及记录的查询、更新、删除、多表关联查询

SQLAlchemy是Python的ORM库&#xff0c;支持多种数据库。 建立连接 连接MySQL要用到Engine&#xff0c;Engine集成了连接池pool和方言Dialect&#xff08;支持不通数据库的SQL语法&#xff09;&#xff0c;最后都统一成标准DBAPI。 from sqlalchemy import create_engine en…

TypeScript

现在说起TypeScript想必大家都不会陌生的&#xff0c;当初从碎片信息中了解TypeScript&#xff0c;我认为他的变量声明和Rust语言有几分相似&#xff0c;是一门比较严格的语言&#xff0c;今天正式的来学习他 JavaScript易学习&#xff0c;易用&#xff0c;以至于大多数人对于…