[linux内核][linux中断]——软中断机制

点击打开链接

一,linux软中断的概念
软中断(softirq)常常表示可延迟函数的所有种类,目前linux上使用的软中断个数是有限的,linux最多注册32个,目前使用了10个,在interrupt.h中定义,中断上下文:表示内核当前正在执行一个中断处理程序或者一个可延迟函数。软中断(即使同一类型的软中断)可以并发运行在多个CPU上,因此软中断是可重入函数必须使用自旋锁保护其数据结构。一个软中断不会去抢占另外一个软中断。

软中断和tasklet的区别
由于软中断必须使用可重入函数,这就导致设计上的复杂度变高,作为设备驱动程序的开发者来说,增加了负担。而如果某种应用并不需要在多个CPU上并行执行,那么软中断其实是没有必要的。因此诞生了弥补以上两个要求的tasklet。它具有以下特性:
a)一种特定类型的tasklet只能运行在一个CPU上,不能并行,只能串行执行。
b)多个不同类型的tasklet可以并行在多个CPU上。
c)软中断是静态分配的,在内核编译好之后,就不能改变。但tasklet就灵活许多,可以在运行时改变(比如添加模块时)。

软中断的实现:
软中断由softirq_action结构体表示

[cpp] view plaincopy

  1. struct softirq_action{
  2. void (*action)(struct sotfirq_action*)
  3. kernel/softirq.c中定义了一个包含有32个该结构体的数组
  4. static struct softirq_action softirq_vec[NR_SOFTIRQS]

1,注册软中断函数 open_softirq

[cpp] view plaincopy

  1. void open_softirq(int nr, void (*action)(struct softirq_action *))
  2. {
  3. /* softirq_vec是个struct softirq_action类型的数组 */
  4. softirq_vec[nr].action = action;
  5. }

2,触发软中断的函数 raise_softirq 参见 kernel/softirq.c文件

[cpp] view plaincopy

  1. void raise_softirq(unsigned int nr)
  2. {
  3. unsigned long flags;
  4. local_irq_save(flags);
  5. raise_softirq_irqoff(nr);
  6. local_irq_restore(flags);
  7. }

3,执行软中断 do_softirq 参见 kernel/softirq.c文件,如果有待处理的软中断,do_softirq()会循环遍历每一个,调用它们的处理程序。

[cpp] view plaincopy

  1. asmlinkage void do_softirq(void)
  2. {
  3. __u32 pending;
  4. unsigned long flags;
  5. /* 判断是否在中断处理中,如果正在中断处理,就直接返回 */
  6. if (in_interrupt())
  7. return;
  8. /* 保存当前寄存器的值 */
  9. local_irq_save(flags);
  10. /* 取得当前已注册软中断的位图 */
  11. pending = local_softirq_pending();
  12. /* 循环处理所有已注册的软中断 */
  13. if (pending)
  14. __do_softirq();
  15. /* 恢复寄存器的值到中断处理前 */
  16. local_irq_restore(flags);
  17. }

4,执行相应的软中断 - 执行自己写的中断处理linux中,执行软中断有专门的内核线程,每个处理器对应一个线程,名称ksoftirqd/n

时间: 2024-11-05 13:04:01

[linux内核][linux中断]——软中断机制的相关文章

Linux内核实现中断和中断处理(二)

上回说了Linux内核实现中断会把中断分为两部分进行处理,上回讲了上部分,这回讲下部分的设计思路 下半部的实现机制 软中断 tasklet:是通过软中断实现的,但和软中断有所不同 工作队列 讲上面几个实现机制之前先讲一个古老的方法,现在版本的内核虽然已经不再食用了,但是思想还在继续使用 最早的Linux只提供了“bottom half”这种机制实现下半部分,被称为BH,实现简单粗暴,设置一个全局变量(32位整数),表示一个32个节点的链表队列,哪位设置为1证明哪个bottom half就可以执行

再思linux内核在中断路径内不能睡眠/调度的原因(2010)【转】

转自:http://blog.csdn.net/maray/article/details/5770889 Linux内核中断路径中不能睡眠,为什么? 这里就行了很深入的讨论,值得一看:http://bbs2.chinaunix.net/viewthread.php?tid=1618430 但是,他们的讨论最后没有得出一个明确的结论.其中,cskyrain在8楼 的思考触及到了一个要点,但是没有深入展开: [c-sharp] view plain copy 1楼 发表于 2009-11-24 2

深入理解Linux内核-中断和异常

Linux内核代码查看 http://androidxref.com/ 中断:被定义位一个事件,它能改变处理器执行指令的顺序.它对应硬件(CPU.其他硬件设备)电路产生的电信号. 同步中断:指令执行时CPU控制单元产生:称为同步,是因为只有在一条指令终止执行后CPU才回发出中断.也被称为异常 异步中断:其他硬件设备按照CPU时钟信号随机产生的.也被简称中断 中断的约束:1.中断必须尽快处理完成:中断一般被分两部分执行:关键而且紧急的部分,内核立即执行:其余部分内核稍后执行: 2.中断的处理必须能

[linux内核][linux]linux内核时间管理基础

一,linux时间管理基础http://blog.csdn.net/droidphone/article/details/7975694http://blog.csdn.net/smilingjames/article/details/6205540linux所有时间基础都是以低层硬件为基础的,低层硬件有GPT和cpu local timer,比如GPT的时钟源为13M HZlinux低层时间的架构分为clock source,clock event device,clock source上层分

[linux内核]linux内核编程规范

1,__attrubte__关键字的作用 点击打开链接 __attrubte__ ((packed)) 的作用就是告诉编译器取消结构在编译过程中的优化对齐,按照实际占用字节数进行对齐.struct str_struct{        __u8    a;        __u8    b;        __u8    c;        __u16   d;} __attribute__ ((packed));以上结构体的大小为5/*  当用到typedef时,要特别注意__attribut

[linux内核][LINUX内核编程]学习笔记(二)

linux内核————队列 linux内核——队列 定义: [cpp] view plaincopy struct __kfifo{ unsigned int in;  //入队偏移,写索引 unsigned int out;  //出队偏移,读索引 unsigned int mask; unsigned int esize; void *data; } 使用: 创建一个队列,该函数创建并初始化一个大小为size的kfifo: [cpp] view plaincopy 38 int __kfif

linux 内核 linux kernel travel

linux 内核 kernel_核 travel_旅行 linux kernel travel linux 2.6 1 hellomod.c 001 // hello world driver for linux 2.6 #include <linux/module.h>                  /*所有模块都要使用头文件module.h*/ #include<linux/kernel.h>               /*kernel.h包含了常用的内核函数*/ #in

Linux内核(二)中断基本概念

转载请注明出处:jiq?钦's technical Blog 首先解释一些容易混淆的概念: 中断上下文:正在执行ISR或者下半部.没有进程背景(只是暂停CPU去内存中其他地方执行一段快速代码),所以不能被切换(比如睡眠,被其他进程抢占等都不行). 进程上下文:非中断上下文(比如执行系统调用或者内核线程的时候).此时内核代表线程在执行,所以允许睡眠,被抢占等(被切换). 中断栈:每个处理器有一个专门的中断栈.以前中断处理程序都是使用中断进程的内核栈(只有一个),但是内核栈越来越不够用,所以中断处理

[linux内核][linux中断]——内核抢占

1,禁止内核抢占的函数是preempt_disable(),允许内核抢占的方法是preempt_enable() 2,真正的上锁前,为何要调用preempt_disable()来关闭抢占的case http://blog.csdn.net/kasalyn/article/details/11473885 [cpp] view plaincopy static inline void raw_spin_lock(raw_spinlock_t *lock) { preempt_disable();