1.前言

软中断(softirq)是中断处理程序在开启中断的情况下执行的部分,可以被硬中断抢占。把延迟函数叫做软中断并不是因为它是一个真正的中断,而是因为延迟函数主要在中断上下文环境中运行。Linux中最多可以支持32种软中断操作,但目前Linux只实现了其中的几种。

中断号 名称 作用
0 HI_SOFTIRQ 高优先级tasklet
1 TIMER_SOFTIRQ 定时器软中断
2 NET_TX_SOFTIRQ 网络发送软中断
3 NET_RX_SOFTIRQ 网络接收软中断
4 SCSI_SOFTIRQ SCSI设备驱动专用软中断
5 TASKLET_SOFTIRQ 常规tasklet
    include/linux/interrupt.henum{HI_SOFTIRQ=0,TIMER_SOFTIRQ,NET_TX_SOFTIRQ,NET_RX_SOFTIRQ,BLOCK_SOFTIRQ,IRQ_POLL_SOFTIRQ,TASKLET_SOFTIRQ,SCHED_SOFTIRQ,HRTIMER_SOFTIRQ, /* 没有使用,但是保留,因为有些工具依赖这个编号 */RCU_SOFTIRQ,     /* RCU软中断应该总是最后一个软中断 */NR_SOFTIRQS};

2.关键函数

  • 函数open_softirq()用来注册软中断的处理函数,在软中断向量表中为指定的软中断编号设置处理函数。
    kernel/softirq.cvoid open_softirq(int nr, void (*action)(struct softirq_action *)){softirq_vec[nr].action = action;}
  • 函数raise_softirq用来触发软中断,参数是软中断编号。
    void raise_softirq(unsigned int nr);

3.执行软中断

内核执行软中断的地方如下。

  • (1)在中断处理程序的后半部分执行软中断,对执行时间有限制:不能超过2毫秒,并且最多执行10次。
  • (2)每个处理器有一个软中断线程,调度策略是SCHED_NORMAL,优先级是120。
  • (3)开启软中断的函数local_bh_enable()。
    在中断处理程序的后半部分,调用函数irq_exit()以退出中断上下文,处理软中断,其代码如下:
    kernel/softirq.cvoid irq_exit(void){…preempt_count_sub(HARDIRQ_OFFSET);if (! in_interrupt() && local_softirq_pending())invoke_softirq();…}

如果正在处理的硬中断没有抢占正在执行的软中断,没有禁止软中断,并且当前处理器的待处理软中断位图不是空的,那么调用函数invoke_softirq()来处理软中断。

    kernel/softirq.c1   static inline void invoke_softirq(void)2   {3    if (ksoftirqd_running())4         return;56    if (! force_irqthreads) {7         __do_softirq();8    } else {9         wakeup_softirqd();10   }11  }

第3行代码,如果软中断线程处于就绪状态或运行状态,那么让软中断线程执行软中断。第6行和第7行代码,如果没有强制中断线程化,那么调用函数__do_softirq()执行软中断。第8行和第9行代码,如果强制中断线程化,那么唤醒软中断线程执行软中断。函数__do_softirq是执行软中断的核心函数,其主要代码如下:

    kernel/softirq.c1   #define MAX_SOFTIRQ_TIME  msecs_to_jiffies(2)2   #define MAX_SOFTIRQ_RESTART 103   asmlinkage __visible void __softirq_entry __do_softirq(void)4   {5    unsigned long end = jiffies + MAX_SOFTIRQ_TIME;6    unsigned long old_flags = current->flags;7    int max_restart = MAX_SOFTIRQ_RESTART;8    struct softirq_action *h;9    bool in_hardirq;10   __u32 pending;11   int softirq_bit;1213   …14   pending = local_softirq_pending();15   …16   __local_bh_disable_ip(_RET_IP_, SOFTIRQ_OFFSET);17   …1819  restart:20   set_softirq_pending(0);2122   local_irq_enable();2324   h = softirq_vec;2526   while ((softirq_bit = ffs(pending))) {27        …28        h += softirq_bit - 1;29        …30        h->action(h);31        …32        h++;33        pending >>= softirq_bit;34   }3536   …37   local_irq_disable();3839   pending = local_softirq_pending();40   if (pending) {41        if (time_before(jiffies, end) && ! need_resched() &&42            --max_restart)43              goto restart;4445        wakeup_softirqd();46   }4748   …49   __local_bh_enable(SOFTIRQ_OFFSET);50   …51  }

第14行代码,把局部变量pending设置为当前处理器的待处理软中断位图。第16行代码,把抢占计数器的软中断计数加1。第20行代码,把当前处理器的待处理软中断位图重新设置为0。第22行代码,开启硬中断。第26~34行代码,从低位向高位扫描待处理软中断位图,针对每个设置了对应位的软中断编号,执行软中断的处理函数。第37行代码,禁止硬中断。第40行代码,如果软中断的处理函数又触发软中断,处理如下。❑ 第41~43行代码,如果软中断的执行时间小于2毫秒,不需要重新调度进程,并且软中断的执行次数没超过10,那么跳转到第19行代码继续执行软中断。第45行代码,唤醒软中断线程执行软中断。第49行代码,把抢占计数器的软中断计数减1。

4.ksoftirqd

软中断线程每个处理器有一个软中断线程,名称是“ksoftirqd/”后面跟着处理器编号,调度策略是SCHED_NORMAL,优先级是120。软中断线程的核心函数是run_ksoftirqd(),其代码如下:

    kernel/softirq.cstatic void run_ksoftirqd(unsigned int cpu){local_irq_disable();if (local_softirq_pending()) {__do_softirq();local_irq_enable();…return;}local_irq_enable();}

5.参与讨论

==================================

新的文章内容和分享已更新在:

|工|·-·|重|·-·|号|:协议森林

==================================

【Linux内核】Linux软中断处理机制-ksoftirqd相关推荐

  1. linux kernel and user space通信机制,Linux内核与用户空间通信机制研究.pdf

    ISSN 1009-3044 E-mail:info@CCCC.net.CR ComputerKnowledgeandTechnology电脑知识与技术 http://www.dnzs.net.cn ...

  2. 【Linux 内核】宏内核与微内核架构 ( 操作系统需要满足的要素 | 宏内核 | 微内核 | Linux 内核动态加载机制 )

    文章目录 一.操作系统需要满足的要素 二.宏内核 三.微内核 四.Linux 内核动态加载机制 一.操作系统需要满足的要素 电脑上运行的 操作系统 , 是一个 软件 ; 设备管理 : 操作系统需要 为 ...

  3. Linux内核中的platform机制

    Linux内核中的platform机制 从Linux 2.6起引入了一套新的驱动管理和注册机制:platform_device和platform_driver.Linux中大部分的设备驱动,都可以使用 ...

  4. linux 信号优先级,linux内核中的信号机制

    linux内核中的信号机制--信号处理 Kernel version:2.6.14 CPU architecture:ARM920T Author:ce123(http://blog.csdn.net ...

  5. linux 内核 工作队列,Linux内核新旧工作队列机制的剖析和比较

    摘要:在中断驱动的程序设计中,工作队列是一种强有力的工具.但是在Linux2.6.35及其以前的内核版本中,每创建一个工作队列就创建与CPU数目相同的内核线程,耗费大量的内核资源:工作只能严格串行的处 ...

  6. Linux内核中断系统处理机制-详细分析

    原文地址::https://blog.csdn.net/weixin_42092278/article/details/81989449 相关文章 1.Linux中断管理 (1)Linux中断管理机制 ...

  7. Linux内核笔记--软中断

    Linux软中断 1.软中断介绍 2.软中断的使用 2.1.注册软中断处理函数 2.2.触发软中断 1.软中断介绍 Linux 内核使用结构体 softirq_action 表示软中断, softir ...

  8. Linux内核中的RCU机制

    http://blog.chinaunix.net/uid-23769728-id-3080134.html RCU的设计思想比较明确,通过新老指针替换的方式来实现免锁方式的共享保护.但是具体到代码的 ...

  9. 浅析linux内核中的idr机制

           idr在linux内核中指的就是整数ID管理机制,从本质上来说,这就是一种将整数ID号和特定指针关联在一起的机制.这个机制最早是在2003年2月加入内核的,当时是作为POSIX定时器的一 ...

最新文章

  1. Xamarin ios C#苹果应用开发第二讲配置环境和编写代码
  2. 一个项目搞定支付宝,微信支付!
  3. python最适合做什么生意赚钱投资小_2018做什么投资小赚钱快(适合穷人做的简单生意)...
  4. 不要“个人英雄主义”,物联网安全共同体更稳固
  5. SAP Spartacus如何判断用户是否已经成功登录
  6. mysql 开启引擎命令_MySql中启用InnoDB数据引擎的方法
  7. Oracle访问数据的存取方法
  8. 第一张信用卡,该选哪家的?
  9. oracle中文加密算法,Oracle数据库替代加密算法
  10. processing作品代码_创意编程 | Processing的初步学习
  11. 空循环和无穷循环的区别
  12. PermissionError: [Errno 13] in python
  13. java.io.InvalidClassException
  14. 史上最全的ocr文字识别体验,让你一次用个够
  15. Olly's Shadow
  16. 一次使用 Go 语言编写脚本的经历
  17. 诺基亚安卓手机_诺基亚手机,为什么宁可走向衰弱,也不愿采用谷歌的安卓系统?...
  18. 小班关于计算机运用的教案,实用的小班教案四篇
  19. 小伙用C++代码实现P2P穿透文件传输,网友集体打call!
  20. 综合复习(五)——网络编程

热门文章

  1. 大力普及“他妈的”有助于语言交流
  2. Win11资源管理器(文件夹)出现的工具栏怎么隐藏?
  3. 解决问题最高明的方法:打开自己
  4. 【Faster R-CNN论文精度系列】从Faster R-CNN源码中,我们“学习”到了什么?
  5. 求解1+1/2+1/3+...1/99+1/100的和
  6. 小米雷军打出王炸,始料未及的华为余承东一下子懵了
  7. NOI Online 2020 Round1 准备计划
  8. js复制本地文件(单条和批量)
  9. 测试知识之:黑盒白盒和灰盒测试
  10. Vue-DataV 数据可视化工具