本文转载自: http://blog.chinaunix.net/uid-9620812-id-3833377.html,如有需要,请移步访问。

Technorati 标签: Linux 软中断

---------------------------------------我是分割线----------------------------------------

一、软中断注册
和硬中断类似,软中断也有类似的中断向量表,只不过是用“软件”实现的。
struct softirq_action softirq_vec[32]是软中断向量表  
(文件linux_2_6_24/kernel/softirq.c)

  1. struct softirq_action
  2. {
  3.     void (*action)(struct softirq_action *); //钩子函数
  4.     void *data;                              //钩子函数的形参
  5. };

内核用到的中断向量(其实就是数组下标)如下所示
(文件linux_2_6_24/include/linux/interrupt.h)

  1. enum{
  2.     HI_SOFTIRQ=0, //高优先级的tasklet
  3.     TIMER_SOFTIRQ,      //内核定时器
  4.     NET_TX_SOFTIRQ,     //网络发送
  5.     NET_RX_SOFTIRQ,     //网络接收
  6.     BLOCK_SOFTIRQ,      //???
  7.     TASKLET_SOFTIRQ,    //普通的tasklet
  8.     SCHED_SOFTIRQ
  9. }

内核注册一个软中断用函数,本质上就是就是初始化数组某一元素

  1. void open_softirq(int nr, void (*action)(struct softirq_action*), void *data)
  2. {   //nr 即软中断向量编号
  3.     softirq_vec[nr].data = data;
  4.     softirq_vec[nr].action = action;
  5. }

内核注册软中断的地方有:

  1. start_kernel()
  2. -->init_timers()
  3. -->open_softirq(TIMER_SOFTIRQ,run_timer_softirq,NULL)
  4. -->softirq_init()
  5. -->open_softirq(TASKLET_SOFTIRQ, tasklet_action,NULL)
  6. -->open_softirq(HI_SOFTIRQ,tasklet_hi_action,NULL)
  7. -->do_initcall()
  8. -->net_dev_init()
  9. -->open_softirq(NET_TX_SOFTIRQ, net_tx_action, NULL);
  10. -->open_softirq(NET_RX_SOFTIRQ, net_rx_action, NULL);
  11. -->blk_dev_init()
  12. -->open_softirq(BLOCK_SOFTIRQ, blk_done_softirq,NULL)

二、软中断触发
前面注册完了,现在开始触发。
内核用一个数据结构来标记曾经有“软中断”发生过(或者说成软中断被触发过)
__softirq_pending 共32bit,即每个bit对应软中断的一个向量,实际使用了6个bit
第n个bit置1,即softirq_vec[n]有软中断发生。

  1. typedef struct {
  2.     unsigned int __softirq_pending; /* set_bit is used on this */
  3.     unsigned int __last_jiffy_stamp;
  4. } ____cacheline_aligned irq_cpustat_t;
  5. extern irq_cpustat_t irq_stat[]; /* defined in asm/hardirq.h */
  6. #define __IRQ_STAT(cpu, member) (irq_stat[cpu].member)
  7. #define local_softirq_pending() \
  8.     __IRQ_STAT(smp_processor_id(), __softirq_pending)
  9. #define set_softirq_pending(x) (local_softirq_pending() = (x))
  10. #define or_softirq_pending(x) (local_softirq_pending() |= (x))
  11. #define __raise_softirq_irqoff(nr) do { or_softirq_pending(1UL << (nr)); } while (0)

常用的软中断触发函数

  1. void raise_softirq_irqoff(int nr){    //nr 即软中断向量编号
  2.     __raise_softirq_irqoff(nr);
  3. }

但这只是“触发”软中断,软中断并不会立即被处理
三、软中断处理
函数_ _do_softirq是一次性按照向量表从高到低循环处理所有软中断(潜台词,软中断不可嵌套)
_ _do_softirq()的调用时机:
1. irq_exit() 硬件中断处理完,返回时调用

  1. do_IRQ() -->irq_exit()
  2. -->local_softirq_pending()
  3. -->_ _do_softirq()

2. ksoftirqd()  用于辅助处理软中断的内核线程,每一个CPU上都运行着一个ksoftirqd。

  1. start_kernel() --> kernel_init() -->do_pre_smp_initcalls()
  2. -->spawn_ksoftirqd() -->cpu_callback()
  3. -->kthread_create(ksoftirqd, hcpu, "ksoftirqd/%d", hotcpu)
  4. -->ksoftirqd()
  5. -->local_softirq_pending()
  6. -->_ _do_softirq()

3. local_bh_enable()时,发现有待处理的软中断且当时没处在软硬中断上下文中

  1. local_bh_enable()
  2. -->local_softirq_pending()
  3. -->_ _do_softirq()

处理过程代码详解

  1. asmlinkage void __do_softirq(void)
  2. {
  3.     struct softirq_action *h;
  4.     __u32 pending;
  5. int max_restart = MAX_SOFTIRQ_RESTART;
  6. int cpu;
  7.     pending = local_softirq_pending();
  8.     account_system_vtime(current);
  9. /*软中断处理中,禁止软中断再次进入,软中断处理是不可重入的*/
  10.     __local_bh_disable((unsigned long)__builtin_return_address(0));
  11.     trace_softirq_enter();
  12.     cpu = smp_processor_id();
  13. restart:
  14. /* Reset the pending bitmask before enabling irqs
  15.     下面首先清除pending,以便系统可以激活其它软件中断,
  16.     然后使能外部中断
  17.     系统在下面的处理中,将使能外部中断以提高系统的响应,
  18.     注意,必须先清除pending,再使能外部中断,否则死锁*/
  19.     set_softirq_pending(0);
  20.     local_irq_enable();
  21.     h = softirq_vec;
  22. /*下面按照从高到低调用open_softirq注册的句柄*/
  23. do {
  24. if (pending & 1) {
  25. h->action(h); //关键的一句,tasklet、内核timer、网络中断都是在这里搞的
  26.             rcu_bh_qsctr_inc(cpu);
  27. }
  28.         h++;
  29.         pending >>= 1;
  30. } while (pending);
  31.     local_irq_disable();
  32.     pending = local_softirq_pending();
  33. if (pending && --max_restart)
  34.         goto restart;
  35. if (pending)
  36.         wakeup_softirqd();
  37.     trace_softirq_exit();
  38.     account_system_vtime(current);
  39.     _local_bh_enable();
  40. }

Linux 软中断的更多相关文章

  1. linux软中断与硬中断实现原理概述

    linux软中断与硬中断实现原理概述. 1.软中断通过open_softirq注册一个软中断处理函数,即在软中断向量表softirq_vec数组中添加新的软中断处理action函数. 2.调用rais ...

  2. 怎么理解Linux软中断?

    1.什么是中断 中断是系统用来响应硬件设备请求的一种机制,它会打断进程的正常调度和执行,然后调用内核中的中断处理程序来响应设备的请求. 2.为什么要有中断呢? "举个生活中的例子" ...

  3. Linux软中断、tasklet和工作队列

    Linux内核中的软中断.tasklet和工作队列详解 引言 软中断.tasklet和工作队列并不是Linux内核中一直存在的机制,而是由更早版本的内核中的“下半部”(bottom half)演变而来 ...

  4. linux 软中断过高性能优化案例

    案例如下: 发现cpu0上的软中断高达50%

  5. Linux碎碎念

    在学习Linux过程中,有许多有用的小技巧.如果放在纸质的笔记本上,平时查阅会相当不方便.现在以一种“碎碎念”的方式,汇集整理在此,目前还不是很多,但随着学习.工作的深入,后续会陆陆续续添加更多的小技 ...

  6. Intel 80x86 Linux Kernel Interrupt(中断)、Interrupt Priority、Interrupt nesting、Prohibit Things Whthin CPU In The Interrupt Off State

    目录 . 引言 . Linux 中断的概念 . 中断处理流程 . Linux 中断相关的源代码分析 . Linux 硬件中断 . Linux 软中断 . 中断优先级 . CPU在关中断状态下编程要注意 ...

  7. 嵌入式系统Linux内核开发工程师必须掌握的三十道题(转)

    嵌入式系统Linux内核开发工程师必须掌握的三十道题 如果你能正确回答以下问题并理解相关知识点原理,那么你就可以算得上是基本合格的Linux内核开发工程师,试试看! 1) Linux中主要有哪几种内核 ...

  8. Linux中断管理

    CPU和外设之间的交互,或CPU通过轮询机制查询,或外设通过中断机制主动上报. 对大部分外设中断比轮询效率高,但比如网卡驱动采取轮询比中断效率高. 这里重点关注ARM+Linux组合下中断管理,从底层 ...

  9. Linux 驱动开发

    linux驱动开发总结(一) 基础性总结 1, linux驱动一般分为3大类: * 字符设备 * 块设备 * 网络设备 2, 开发环境构建: * 交叉工具链构建 * NFS和tftp服务器安装 3, ...

随机推荐

  1. jQuery代码性能小细节

    选择器Selector的使用 $("#id")使用id来定位DOM元素无疑是最佳提高性能方式,因为jQuery底层将直接调用本地方法document.getElementbyId( ...

  2. cocos2d-x中CCCallFunc CCCallFuncN CCCallFuncND的区别和使用示例

    转自:http://xiandanboke.com.cn/cocos2d-xcccallfunc.html CCCallFunc CCCallFuncN CCCallFuncND的区别和使用 CCCa ...

  3. 转:《JavaScript—之对象参数的引用传递》

    转自:博客园 Wayou http://www.cnblogs.com/Wayou/p/javascript_arguments_passing_with_reference.html 变量 1.Ja ...

  4. The Kernel Newbie Corner: Kernel Debugging with proc "Sequence" Files--Part 2

    转载:https://www.linux.com/learn/linux-career-center/39972-kernel-debugging-with-proc-qsequenceq-files ...

  5. ubuntu11.04编译TQ2440 Qt2.2.0 成功

    转:http://blog.csdn.net/xuehui869/article/details/8958311 运行主机:ubuntu 32位 11.04QT版本:2.2.0开发板:TQ2440源码 ...

  6. 常见hash算法的原理

    散列表,它是基于快速存取的角度设计的,也是一种典型的“空间换时间”的做法.顾名思义,该数据结构可以理解为一个线性表,但是其中的元素不是紧密排列的,而是可能存在空隙. 散列表(Hash table,也叫 ...

  7. C# 之 FileSystemWatcher事件多次触发的解决方法

    1.问题描述  程序里需要监视某个目录下的文件变化情况: 一旦目录中出现新文件或者旧的文件被覆盖,程序需要读取文件内容并进行处理.于是使用了下面的代码: public void Initial() { ...

  8. WPF 之 资源(Resource)

    1.什么叫WPF的资源(Resource)? 资源是保存在可执行文件中的一种不可执行数据.在WPF的资源中,几乎可以包含图像.字符串等所有的任意CLR对象,只要对象有一个默认的构造函数和独立的属性. ...

  9. jsp包含的讲解

    <%@page language="java" import="java.util.*" pageEncoding="UTF-8"%& ...

  10. 1.5.8 语言分析器(Analyzer)

    语言分析器(Analyzer) 这部分包含了分词器(tokenizer)和过滤器(filter)关于字符转换和使用指定语言的相关信息.对于欧洲语言来说,tokenizer是相当直接的,Tokens被空 ...