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

Linux内核软中断分析

一、软中断类型

在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.kler.cn/a/613045.html

相关文章:

  • AWS AI学习笔记:机器学习的模式及选择
  • 【CVE-2025-30208】| Vite-漏洞分析与复现
  • 自动化构建攻略:Jenkins + Gitee 实现 Spring Boot 项目自动化构建
  • ICLR 2025|华科OVTR:首次实现端到端开放词汇多目标跟踪,刷新性能SOTA!
  • 寻找两个正序数组的中位数
  • 启山智软实现b2c单商户商城对比传统单商户的优势在哪里?
  • 多省发布!第27届中国机器人及人工智能大赛各赛区比赛通知
  • 怎么在一台服务器上配置两套不同的前后端分离系统
  • 安装Webpack并创建vue项目
  • QT_demo1_calculator
  • 跨境TRS投资操作指南与系统解决方案
  • 关于bug总结记录
  • Java 中各种锁的使用详解
  • Node.js 如何发布一个 NPM 包——详细教程
  • 第R9周:阿尔兹海默症诊断(优化特征选择版)
  • 美摄科技智能汽车车内实时AR特效方案,让出行充满乐趣
  • 神经网络知识
  • 【极速版 -- 大模型入门到进阶】LORA:大模型轻量级微调
  • 智能网联交通加速落地,光路科技TSN技术助推车路云一体化发展
  • 跟着尚硅谷学vue-day1