Linux内核软中断分析

news2025/4/1 6:00:13

一、软中断类型

在Linux内核中,中断处理分为上半部(硬中断)和下半部。上半部负责快速响应硬件事件,而下半部用于处理耗时任务,避免阻塞系统。下半部有三种机制:软中断(Softirq)小任务(Tasklet)工作队列(Workqueue)。它们的区别如下:


1. 软中断(Softirq)

  • 特点

    • 不允许睡眠:在中断上下文中执行,不能调用可能引发睡眠的函数(如kmalloc(GFP_KERNEL))。

    • 静态定义:类型在编译时确定(如网络、定时器等),无法动态添加新类型。

    • 可重入与并发:同类型软中断可在多个CPU上并行执行,处理函数需支持可重入,需用锁保护临界区。

  • 示例

    • 网络数据包处理:网卡硬中断将数据包存入队列后,触发NET_RX_SOFTIRQ软中断。多个CPU可同时调用处理函数net_rx_action(),并行处理不同数据包。函数内部需使用自旋锁保护共享队列。


2. 小任务(Tasklet)

  • 特点

    • 不允许睡眠:同样在中断上下文中运行。

    • 动态调度:可在运行时动态注册和调度(如驱动初始化时)。

    • 串行执行:同一Tasklet实例仅在一个CPU上执行,无需处理可重入问题。

  • 示例

    • USB设备中断处理:硬中断快速确认中断后,调度Tasklet处理数据传输。例如:

    • void usb_tasklet_func(unsigned long data) { /* 处理数据 */ }
      DECLARE_TASKLET(usb_tasklet, usb_tasklet_func, 0);
      
      // 硬中断中调用:
      tasklet_schedule(&usb_tasklet);

      即使系统有多个CPU,usb_tasklet同一时刻只在一个CPU上运行。


3. 工作队列(Workqueue)

  • 特点

    • 允许睡眠:在进程上下文中运行(内核线程),可使用阻塞函数(如msleep()mutex_lock())。

    • 动态管理:可动态创建队列和任务。

    • 线程执行:任务由内核线程按顺序处理。

  • 示例

    • 磁盘写入操作:需要休眠等待I/O完成时,使用工作队列:

    • struct work_struct write_work;
      
      void write_work_func(struct work_struct *work) {
          // 调用可能阻塞的函数,如文件写入
          filp->f_op->write(...);
      }
      
      // 初始化并提交任务:
      INIT_WORK(&write_work, write_work_func);
      schedule_work(&write_work);

      工作队列处理函数可安全调用write()等可能阻塞的操作。


三者的对比总结

特性软中断小任务工作队列
是否允许睡眠
动态添加/删除否(静态编译时定义)是(可动态创建队列)
并发性多CPU并行,需可重入单CPU串行,无需可重入按线程调度,顺序执行

        软中断(softirq)是中断处理程序在开启中断的情况下执行的部分,可以被硬中断抢占。内核定义了一张软中断向量表,每种软中断有一个唯一编号,对应一个softirq_action实例,内核源码如下:

 软中断类型内核源码如下:

 

二、注册软中断以及触发软中断

        函数open_softirq()来注册软中断处理函数,在软中断向量表中为指定的软中断编号设置处理函数,内核源码如下:

        函数raise_softirq()用来触发软中断,参数是软中断编号:

 

 三、执行软中断

         在中断处理程序的后半部分执行软中断,对执行时间有限制:不能超过 2 毫秒,并且最多执行 10 次;每个处理器有一个软中断线程,调度策略是 SCHED_NORMAL,优先级是120。

        中断处理程序执行软中断:

         软中断线程:

         以NIC网卡接收数据触发软中断为例,讲解这些函数工作流程:

1. open_softirq

  • 功能:用于注册软中断处理函数。在内核中,软中断类型是预先定义好的 ,如NET_RX_SOFTIRQ(网卡接收数据软中断类型)。通过open_softirq(net_rx_softirq, net_rx_action),将net_rx_action函数注册为NET_RX_SOFTIRQ软中断的处理函数。这样当该软中断被触发时,内核知道要调用哪个函数来处理。
  • 流程:将传入的处理函数指针赋值给对应软中断向量表(softirq_vec数组 )中该软中断类型索引位置的action成员。

2. raise_softirq

  • 功能:标记要触发的软中断,使其进入待处理状态。当 NIC 网卡接收到数据时,相关代码会调用raise_softirq来触发NET_RX_SOFTIRQ软中断。
  • 流程
    • 首先调用raise_softirq_irqoff,该函数通过__raise_softirq_irqoff设置当前 CPU 的软中断 pending 标志位(对应__softirq_pendingNET_RX_SOFTIRQ相关位) ,表示有软中断等待处理。
    • 然后检查当前是否不在中断上下文(通过in_interrupt判断) ,如果满足条件,就唤醒软中断守护进程ksoftirqd(调用wakeup_softirqd),准备处理软中断;若在中断上下文,则软中断会在中断退出阶段处理。

3. irq_exit

  • 功能:在硬中断处理完成后调用,用于退出中断上下文,并检查是否有需要处理的软中断。当 NIC 网卡硬中断处理完成后,会执行到irq_exit
  • 流程
    • 执行一些统计和追踪相关操作,如account_system_vtime(current)trace_hardirq_exit
    • 通过sub_preempt_count(IRQ_EXIT_OFFSET)标识 HARDIRQ 中断上下文结束。
    • 使用in_interrupt判断当前是否处于中断上下文,用local_softirq_pending检查是否有等待处理的软中断。若不在中断上下文且有软中断等待处理,则调用invoke_softirq

4. invoke_softirq

  • 功能:实际触发软中断处理,它是__do_softirq的宏定义(#define invoke_softirq() __do_softirq() ),负责调用软中断处理函数。
  • 流程:直接调用__do_softirq,进入软中断处理核心流程。

5. _do_softirq

  • 功能:软中断处理核心函数,遍历并执行处于 pending 状态的软中断处理函数。
  • 流程
    • 获取当前 CPU 软中断位图pending = local_softirq_pending(),得到哪些软中断被触发。
    • 禁止本地 CPU 的软中断(__local_bh_disable ),防止处理过程中软中断被干扰。
    • 标记进入 softirq context(lockdep_softirq_enter ),记录相关锁依赖信息。
    • 循环处理位图中的软中断:
      • 对位图清零(set_softirq_pending(0) )。
      • 开启本地 CPU 硬中断(local_irq_enable ),允许硬中断打断软中断处理(但软中断不可嵌套)。
      • 获取软中断描述(h = softirq_vec ),根据软中断位图找到对应的软中断处理函数并执行(h->action(h) ) 。
      • 处理过程中检查是否超时(通过jiffies和设定的最大处理时间MAX_SOFTIRQ_TIME比较 )和达到最大重启次数(max_restart ,默认 10 次) ,若满足条件且还有软中断未处理完,则唤醒ksoftirqd继续处理剩余软中断。
    • 处理完成后恢复相关设置,如关闭本地 CPU 硬中断等。

6. run_softirqd

  • 功能ksoftirqd内核线程执行的函数,当软中断处理在irq_exit中未处理完,或内核其他代码主动触发软中断且不在中断上下文时,ksoftirqd会被唤醒执行run_softirqd来处理软中断。
  • 流程:在内核关闭抢占的情况下调用__do_softirq,执行与上述__do_softirq类似的软中断处理流程,遍历并执行等待处理的软中断处理函数。

 https://github.com/0voice

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

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

相关文章

Linux修改默认shell为zsh

一、修改模型shell为zsh 1、检查当前使用的shell echo $SHELL 2、检查当前系统支持的shell cat /etc/shells# 输出结果显示如下: """ /bin/sh /bin/bash /usr/bin/sh /usr/bin/bash /bin/csh /bin/tcsh /usr/bin/csh /usr/bin/tcsh /usr/bin/zsh…

[ComfyUI] 如何升级自定义节点(Custom Nodes)

ComfyUI 提供了灵活的 自定义节点(Custom Nodes) 功能,允许用户扩展其能力。随着插件的更新,保持 Custom Nodes 处于最新状态是确保兼容性和功能完整性的关键。 1. 手动升级(Git Pull 方式) 如果你的 自定义节点 是通过 Git 克隆的,可以使用 Git 命令来升级: 步骤: …

linux和windows是采用何种机制保存密码的?

传统Linux的不足: 1)存在特权用户root 任何人只要得到root的权限,对于整个系统都可以为所欲为。这一点Windows也一样。 2)对于文件的访问权划分不够细 在linux系统里,对于文件的操作,只有「所有者」…

matlab打开两个工程

1、问题描述 写代码时,需要实时参考别人的代码,需要同时打开2个模型,当模型在同一个工程内时,这是可以直接打开的,如图所示 2、解决方案 再打开一个MATLAB主窗口 这个时候就可以同时打开多个模型了 3、正确的打开方…

HarmonyOS主题管理工具封装:动态切换、持久化存储与常见问题解析

注:适用版本(Harmony OS NEXT / 5.0 / API 12 ) 一、效果展示 二、技术栈 HarmonyOS ArkUI框架 使用AppStorage实现跨组件状态管理,PersistentStorage持久化存储用户偏好。 系统配置常量 ConfigurationConstant.Color…

60V单通道高精度线性恒流LED驱动器防60V反接SOD123封装

产品描述: PC561A 系列产品是用于产生单通道、高精度恒流源( Constant Current Regulator, CCR) 的LED 驱动芯片,为各类 LED 照明应用提供高性价比恒流方案。PC561A 采用晶体管自偏置技术,可在超宽工作电压范围内维持…

学习threejs,使用Sprite精灵、SpriteMaterial精灵材质

👨‍⚕️ 主页: gis分享者 👨‍⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍⚕️ 收录于专栏:threejs gis工程师 文章目录 一、🍀前言1.1 ☘️THREE.Sprite1.1.1 ☘️代码…

Cent OS7+Docker+Dify

由于我之前安装了Dify v1.0.0,出现了一些问题:无法删除,包括:知识库中的文件、应用、智能体、工作流,都无法删除。现在把服务器初始化,一步步重新安装,从0到有。 目录 1、服务器重装系统和配置…

本地AI大模型部署革命:Ollama部署和API调试教程

Ollama:你的私人AI助手 还在为云端AI服务的高昂费用和隐私问题而烦恼吗?Ollama横空出世,它是一款专为本地环境打造的大模型部署神器,让你轻松在自己的设备上运行各种强大的AI模型。无论你是开发者还是普通用户,Ollama…

centos7 linux VMware虚拟机新添加的网卡,能看到网卡名称,但是看不到网卡的配置文件

问题现象:VMware虚拟机新添加的网卡,能看到网卡,但是看不到网卡的配置文件 解决方案: nmcli connection show nmcli connection add con-name ens36 ifname ens36 type ethernet #创建一个网卡连接配置文件,这里con…

K8S学习之基础五十一:k8s部署jenkins

k8s部署jenkins 创建nfs共享目录, mkdir -p /data/v2 echo /data/v2 *(rw,no_root_squash) > /etc/exports exportfs -arv创建pv、pvc vi pv.yaml apiVersion: v1 kind: PersistentVolume metadata:name: jenkins-k8s-pv spec:capacity:storage: 1GiaccessMod…

在 Mermaid 流程图里“驯服”quot;的魔法指南!!!

🐉 在 Mermaid 流程图里“驯服”"的魔法指南 在使用 Mermaid 画流程图时,是不是经常遇到想秀一波 " 却被它“反杀”的情况?🎯 今天就来教大家如何在这头代码野兽的嘴里,抢回我们的双引号实体编码&#…

GitHub美化个人主页3D图表显示配置操作

这个功能主要是用的这个开源仓库:https://github.com/yoshi389111/github-profile-3d-contrib 想看效果的话,我的个人主页:https://github.com/Sjj1024 开始操作 1.创建自己的github主页属性项目——跟你github用户名一致即可,…

HarmonyOS NEXT 鸿蒙中关系型数据库@ohos.data.relationalStore API 9+

核心API ohos.data.relationalStore API 9 数据库 数据库是存储和管理数据的系统 数据库(Database)是一个以特定方式组织、存储和管理数据的集合,通常用于支持各种应用程序和系统的运行。它不仅是存放数据的仓库,还通过一定的…

【JavaScript】JavaScript Promises实践指南

【JavaScript】JavaScript Promises实践指南 你了解JavaScript中的Promises吗?这是一个很多人一开始就放弃的主题,但我会尽量让它变得尽可能简单。 1. “Promise”到底是什么? “Promise”是异步编程中的一个基本概念,特别是在J…

git push的时候出现无法访问的解决

fatal: 无法访问 https://github.com/...:gnutls_handshake() failed: Error in the pull function. push的时候没有输入自己的github账号密码,为了解决每次push都要登录github这个问题,采用ssh密钥的方式认证,可以免去每次都输入…

为什么大模型在 OCR 任务上表现不佳?

编者按: 你是否曾经用最先进的大语言模型处理企业文档,却发现它把财务报表中的“$1,234.56”读成了“123456”?或者在处理医疗记录时,将“0.5mg”误读为“5mg”?对于依赖数据准确性的运营和采购团队来说,这…

HCIP(VLAN综合实验)

实验拓补图 实验分析 一、实验目的 掌握VLAN的创建和配置方法理解VLAN在局域网中的作用学习如何通过VLAN实现网络隔离和通信 二、实验环境 交换机(SW1、SW2、SW3)个人电脑(PC1、PC2、PC3、PC4、PC5、PC6)路由器(R1…

每日算法-250328

记录今天学习和解决的LeetCode算法题。 92. 反转链表 II 题目 思路 本题要求反转链表中从 left 到 right 位置的节点。我们可以采用 头插法 的思路来反转指定区间的链表。 具体来说,我们首先定位到 left 位置节点的前一个节点 prev。然后,从 left 位置…

从 Word 到 HTML:使用 Aspose.Words 轻松实现 Word 文档的高保真转换

从 Word 到 HTML:使用 Aspose.Words 轻松实现 Word 文档的高保真转换 前言一、环境准备二、核心代码实现1. 将 Word 转换为 HTML 文件流2. 优化超链接样式 三、测试效果四、总结 前言 在日常开发中,我们经常需要将 Word 文档转换为 HTML,用于…