Linux 软中断
本文转载自: http://blog.chinaunix.net/uid-9620812-id-3833377.html,如有需要,请移步访问。
---------------------------------------我是分割线----------------------------------------
一、软中断注册
和硬中断类似,软中断也有类似的中断向量表,只不过是用“软件”实现的。
struct softirq_action softirq_vec[32]是软中断向量表
(文件linux_2_6_24/kernel/softirq.c)
- struct softirq_action
- {
- void (*action)(struct softirq_action *); //钩子函数
- void *data; //钩子函数的形参
- };
内核用到的中断向量(其实就是数组下标)如下所示
(文件linux_2_6_24/include/linux/interrupt.h)
- enum{
- HI_SOFTIRQ=0, //高优先级的tasklet
- TIMER_SOFTIRQ, //内核定时器
- NET_TX_SOFTIRQ, //网络发送
- NET_RX_SOFTIRQ, //网络接收
- BLOCK_SOFTIRQ, //???
- TASKLET_SOFTIRQ, //普通的tasklet
- SCHED_SOFTIRQ
- }
内核注册一个软中断用函数,本质上就是就是初始化数组某一元素
- void open_softirq(int nr, void (*action)(struct softirq_action*), void *data)
- { //nr 即软中断向量编号
- softirq_vec[nr].data = data;
- softirq_vec[nr].action = action;
- }
内核注册软中断的地方有:
- start_kernel()
- -->init_timers()
- -->open_softirq(TIMER_SOFTIRQ,run_timer_softirq,NULL)
- -->softirq_init()
- -->open_softirq(TASKLET_SOFTIRQ, tasklet_action,NULL)
- -->open_softirq(HI_SOFTIRQ,tasklet_hi_action,NULL)
- -->do_initcall()
- -->net_dev_init()
- -->open_softirq(NET_TX_SOFTIRQ, net_tx_action, NULL);
- -->open_softirq(NET_RX_SOFTIRQ, net_rx_action, NULL);
- -->blk_dev_init()
- -->open_softirq(BLOCK_SOFTIRQ, blk_done_softirq,NULL)
二、软中断触发
前面注册完了,现在开始触发。
内核用一个数据结构来标记曾经有“软中断”发生过(或者说成软中断被触发过)
__softirq_pending 共32bit,即每个bit对应软中断的一个向量,实际使用了6个bit
第n个bit置1,即softirq_vec[n]有软中断发生。
- typedef struct {
- unsigned int __softirq_pending; /* set_bit is used on this */
- unsigned int __last_jiffy_stamp;
- } ____cacheline_aligned irq_cpustat_t;
- extern irq_cpustat_t irq_stat[]; /* defined in asm/hardirq.h */
- #define __IRQ_STAT(cpu, member) (irq_stat[cpu].member)
- #define local_softirq_pending() \
- __IRQ_STAT(smp_processor_id(), __softirq_pending)
- #define set_softirq_pending(x) (local_softirq_pending() = (x))
- #define or_softirq_pending(x) (local_softirq_pending() |= (x))
- #define __raise_softirq_irqoff(nr) do { or_softirq_pending(1UL << (nr)); } while (0)
常用的软中断触发函数
- void raise_softirq_irqoff(int nr){ //nr 即软中断向量编号
- __raise_softirq_irqoff(nr);
- }
但这只是“触发”软中断,软中断并不会立即被处理
三、软中断处理
函数_ _do_softirq是一次性按照向量表从高到低循环处理所有软中断(潜台词,软中断不可嵌套)
_ _do_softirq()的调用时机:
1. irq_exit() 硬件中断处理完,返回时调用
- do_IRQ() -->irq_exit()
- -->local_softirq_pending()
- -->_ _do_softirq()
2. ksoftirqd() 用于辅助处理软中断的内核线程,每一个CPU上都运行着一个ksoftirqd。
- start_kernel() --> kernel_init() -->do_pre_smp_initcalls()
- -->spawn_ksoftirqd() -->cpu_callback()
- -->kthread_create(ksoftirqd, hcpu, "ksoftirqd/%d", hotcpu)
- -->ksoftirqd()
- -->local_softirq_pending()
- -->_ _do_softirq()
3. local_bh_enable()时,发现有待处理的软中断且当时没处在软硬中断上下文中
- local_bh_enable()
- -->local_softirq_pending()
- -->_ _do_softirq()
处理过程代码详解
- asmlinkage void __do_softirq(void)
- {
- struct softirq_action *h;
- __u32 pending;
- int max_restart = MAX_SOFTIRQ_RESTART;
- int cpu;
- pending = local_softirq_pending();
- account_system_vtime(current);
- /*软中断处理中,禁止软中断再次进入,软中断处理是不可重入的*/
- __local_bh_disable((unsigned long)__builtin_return_address(0));
- trace_softirq_enter();
- cpu = smp_processor_id();
- restart:
- /* Reset the pending bitmask before enabling irqs
- 下面首先清除pending,以便系统可以激活其它软件中断,
- 然后使能外部中断
- 系统在下面的处理中,将使能外部中断以提高系统的响应,
- 注意,必须先清除pending,再使能外部中断,否则死锁*/
- set_softirq_pending(0);
- local_irq_enable();
- h = softirq_vec;
- /*下面按照从高到低调用open_softirq注册的句柄*/
- do {
- if (pending & 1) {
- h->action(h); //关键的一句,tasklet、内核timer、网络中断都是在这里搞的
- rcu_bh_qsctr_inc(cpu);
- }
- h++;
- pending >>= 1;
- } while (pending);
- local_irq_disable();
- pending = local_softirq_pending();
- if (pending && --max_restart)
- goto restart;
- if (pending)
- wakeup_softirqd();
- trace_softirq_exit();
- account_system_vtime(current);
- _local_bh_enable();
- }
Linux 软中断的更多相关文章
- linux软中断与硬中断实现原理概述
linux软中断与硬中断实现原理概述. 1.软中断通过open_softirq注册一个软中断处理函数,即在软中断向量表softirq_vec数组中添加新的软中断处理action函数. 2.调用rais ...
- 怎么理解Linux软中断?
1.什么是中断 中断是系统用来响应硬件设备请求的一种机制,它会打断进程的正常调度和执行,然后调用内核中的中断处理程序来响应设备的请求. 2.为什么要有中断呢? "举个生活中的例子" ...
- Linux软中断、tasklet和工作队列
Linux内核中的软中断.tasklet和工作队列详解 引言 软中断.tasklet和工作队列并不是Linux内核中一直存在的机制,而是由更早版本的内核中的“下半部”(bottom half)演变而来 ...
- linux 软中断过高性能优化案例
案例如下: 发现cpu0上的软中断高达50%
- Linux碎碎念
在学习Linux过程中,有许多有用的小技巧.如果放在纸质的笔记本上,平时查阅会相当不方便.现在以一种“碎碎念”的方式,汇集整理在此,目前还不是很多,但随着学习.工作的深入,后续会陆陆续续添加更多的小技 ...
- Intel 80x86 Linux Kernel Interrupt(中断)、Interrupt Priority、Interrupt nesting、Prohibit Things Whthin CPU In The Interrupt Off State
目录 . 引言 . Linux 中断的概念 . 中断处理流程 . Linux 中断相关的源代码分析 . Linux 硬件中断 . Linux 软中断 . 中断优先级 . CPU在关中断状态下编程要注意 ...
- 嵌入式系统Linux内核开发工程师必须掌握的三十道题(转)
嵌入式系统Linux内核开发工程师必须掌握的三十道题 如果你能正确回答以下问题并理解相关知识点原理,那么你就可以算得上是基本合格的Linux内核开发工程师,试试看! 1) Linux中主要有哪几种内核 ...
- Linux中断管理
CPU和外设之间的交互,或CPU通过轮询机制查询,或外设通过中断机制主动上报. 对大部分外设中断比轮询效率高,但比如网卡驱动采取轮询比中断效率高. 这里重点关注ARM+Linux组合下中断管理,从底层 ...
- Linux 驱动开发
linux驱动开发总结(一) 基础性总结 1, linux驱动一般分为3大类: * 字符设备 * 块设备 * 网络设备 2, 开发环境构建: * 交叉工具链构建 * NFS和tftp服务器安装 3, ...
随机推荐
- C#实现ByteBuffer类 .
在写网络程序的时候,经常需要往一个数组里面压数据或者取数据,而Java中再Java.nio中有个ByteBuffer能很方便的实现,Delphi中也有个Stream类有着同样的功能,这里我就模仿JAV ...
- iLinuxBot: Designing Botnets to Manage Linux Clients
转:http://www.linuxforu.com/2012/05/ilinuxbot-designing-botnets-to-manage-linux-clients/ By Nishant S ...
- 图解java8 stream 的几个转换方法
图片摘自:http://ifeve.com/stream/ 1.distinct 对于stream中包含的元素进行去重复操作(去重复依赖元素的equals方法) 2.filter 对于stream中包 ...
- C++ atol
函数名: atol 功 能: 把字符串转换成长整型数 用 法: long atol(const char *nptr); 简介编辑 相关函数: atof,atoi,strtod,strtol,st ...
- 关于URLEncoder的编码和URLDecode解码
在我们开发中,很多时候会遇见各种编码乱码的问题,其实这都是编码不一致的问题,如果你懂得了关于URLEncoder的编码和URLDecode解码,那么问题就会随之消失! 下面我们看看关于编码的代码: [ ...
- Java优先级队列
package com.lk.A; import java.util.PriorityQueue; public class Test5 { public static void main(Strin ...
- JAVA 多态的一种实现
今天一个同事问我一个问题,就是关于子类,父类之间方法的调用这里的.这里我整理了一个小DEMO. 代码如下: 父类的代码: public abstract class ClassA { public f ...
- Gstreamer基本概念介绍(开发前必读)
1. 元件(Elements) 元件(element)是GStreamer中最重要的概念.你可以通过创建一系列的元件(Elements),并把它们连接起来,从而让数据流在这个被连接的各个元件(Elem ...
- PHP计算中英混输字符串长度
最近做项目中碰到需要post value length check的这么一个情况 有这么一个需求, 需要backend来处理post过来的中英混输的数据. 对其限制的规则是中文10个字符, 英文20个 ...
- AjaxPro.2使用小结
这是我最近没事的时候研究的东东,使用AjaxPro.2.dll,从前台调用后台Ajax方法,希望对各位亲有帮助哦.. 1.首先将AjaxPro.2.dll从网上下载下来,打开VS项目,点击项目,右键- ...