Linux Kernel中irq handler, softirq handler 和 tasklet 是比较容易混淆的概念,下面整理一下。

Irq handler通常被称为中断执行的TOP Half,softirq和tasklet被称为bottom half。它们的执行次序可见下图:

某硬件interrupt line触发irq—>(interrupt line disabled)—->cpu进入irq exception—->根据irq触发的interrupt line,调用相应的irq handler—->(interrupt line enabled)—->判断是不是在嵌套的irq handler里,如果不是(最后一层irq)—->preempt disable—->根据irq_stat[CPU_NUM]里被置位的bit,运行相应的softirq handler—->如果irq_stat[TASKLET_SOFTIRQ]被置位,那么tasklet handler的链表将作为softirq_vec[TASKLET_SOFTIRQ]的handler被执行—->所有置位的softirq handler都执行完了—->preempt enable—->irq返回。

irq handler:

实际响应硬件irq的服务程序,通常由request_irq(IRQ_NUM, irq_handler, flags, name, dev)函数注册。硬件中断发生后(即IRQ_NUM被触发后),irq_handler首先被执行。

  • irq handler执行的时候系统处于以下状态:

    1. 在所有cpu上触发该中断的interrupt line被disable。因此在执行irq handler的时候,该irq不会在任何CPU上再触发。如果request_irq()的时候所有flags = IRQF_SHARED,那么所有shared同一interrupt line的irq handler都不会被触发。其他interrupt line的irq还是会触发。
    2. 如果flags = IRQF_DISABLED,那么除了上面所述的1以外,在触发该中断的cpu上的所有中断都被disable了。在其他cpu上中断还会触发。

softirq handler:

在irq执行后,Interrupt line将被重新enable,此时该中断将可能再次触发。此后将执行softirq handler。所以在softirq handler执行的时候,任何中断都可能触发。

softirq handler 是一组静态函数指针数组,定义在softirq_vec[NR_SOFTIRQS]中,类型为struct softirq_action。数组里的每个索引对应一个特定的softirq事件的handler。如index 0对应softirq事件是Hi tasklet,index 2对应的是timer softirq,index 6对应的是tasklet。

  • softirq存在的意义:
    尽可能减少在irq handler里做的事情,使irq handler尽快返回。把大部分可以延迟做得事情放在softirq里做。这就是所谓的TOP HALF和BOTTOM HALF。
    因为irq handler执行的时候至少触发的interrupt line是disable的,如果一个irq handler执行的时间很长,下一个中断就无法相应。一般硬件外设通过interrupt来指示收到数据,长时间不响应中断就造成数据在硬件的FIFO里没有及时搬走,FIFO满了就不能再收数据,从而导致数据丢失。

  • softirq怎样被触发:

当需要softirq启动的时候,调用raise_softirq_irqoff(softirq_num)来将irq_stat[NR_CPUS]对应的bit置位。那么下一次Iraq handler执行完之后被置位的那些softirq handler就会执行。请注意,每个cpu都有一个独立的irq_stat,同一个softirq的bit可能同时在多个cpu的irq_stat中被置位,因此一个softirq handler可能在多个cpu上同时被执行,softirq handler需要考虑同时执行的互斥问题。

tasklet handler:

tasklet有两种:tasklet和hi prority tasklet。前者对应softirq_vec[TASKLET_SOFTIRQ];后者对应softirq_vec[HI_SOFTIRQ]。只是后者排在softirq_vec[]的第一个,所以更早被执行。

下面统称为tasklet.

tasklet其实就是某一种softirq,它的softirq handler是tasklet_action(), 这个函数遵循上面所述的所有softirq的规则。

tasklet handler是注册到tasklet_vec链表上的函数,tasklet_vec链表将在tasklet_action()里被逐个执行。也就是说一个TASKLET_SOFT的softirq handler里执行了一串tasklet handler。

tasklet可以在run time的时候通过tasklet_init()函数动态生成,这与softirq handler必须在编译时就在softirq_vec[]里写好是不同。

tasklet_schedule()函数将tasklet handler注册到tasklet_vec链表上,tasklet_vec是个per cpu data.

一个tasklet handler不会同时在多个cpu上同时运行。更直接的说,tasklet handler只会在运行tasklet_schedule()将其注册到tasklet_vec的那个cpu上运行。这个是由TASKLET_STATE_RUN这个bit控制的。

需要特别注意点:

  1. irq handler, softirq handler和tasklet handler都是工作在interrupt context下的。所以在这三个handler中绝对不可以调用schedule()函数。当然也不可以调用任何使用了schedule()的函数,包 括wait_interruptible, semaphore, mutex等。因为interrupt context没有自己的task structure, 不能进程调度。所以一定要记住irq, softirq和tasklet中绝对不能sleep。另外,在执行这三种handler的时候,preempt是disable的,即使 scheduler timer时间到了,也不会发生抢占。道理是一样的,interrupt context下不能进程调度。在这三种handler执行的过程中唯一能打断它们的只有irq handler。

  2. 同一softirq handler因为能在多个cpu上同时运行,而同一tasklet handler某一时刻只能在一个cpu上运行,所以在SMP的系统上,softirq handler将更及时的被处理,但需要考虑多cpu上运行的互斥问题。在UP的系统上,softirq和tasklet的效率是一样的。

  3. 一般的Driver基本上都是irq+tasklet或irq+workqueue的实现方法。很少会用到静态注册一个softirq,因为很少有实时性 要求必须softirq才能满足的场合。关于workqueue,其实就是一个kernel thread,它的好处是thread能被进程调度,所以wait_interruptible, semaphore, mutex这类sleep的函数(实际上就是调用了sched

Linux Kernel中irq handler, softirq handler 和 tasklet相关推荐

  1. linux kernel中的栈的介绍

    目录 1.linux kernel中的中断irq的栈stack (1).arm32体系的irq的栈 (2).arm64体系的irq的栈 2.linux kernel中的栈stack (1).概念介绍: ...

  2. linux kernel中的进程栈

    1.linux中的user mode的进程栈 在thread_info.h中,设置进程栈的大小为16k #define THREAD_SIZE 16384 #define THREAD_START_S ...

  3. Linux kernel 中模块化的平台驱动代码介绍

    介绍 在linux kernel中通过module_platform_driver来实现模块化平台驱动.大量的设备驱动程序都基于该种方式来实现,使用频次非常的高,在linux kernel 5.4.1 ...

  4. Linux kernel中常见的宏整理

    0x00 宏的基本知识 // object-like #define 宏名 替换列表 换行符 //function-like #define 宏名 ([标识符列表]) 替换列表 换行符 替换列表和标识 ...

  5. Linux Kernel中AEP的现状和发展

    阿里 石洋内核月谈Yesterday AEP简介 AEP是Intel推出的一种新型的非易失Optane Memory设备,又被称作Apache Pass,所以一般习惯称作AEP.在这之前也有类似的设备 ...

  6. 内存访问顺序 - part2: 屏障及Linux kernel中屏障的使用

    文章目录 屏障是什么 Linux Kernel 中的屏障 Linux 屏障 API 一般的屏障 强制性屏障 SMP 条件屏障 隐式屏障 其他屏障 屏障的开销 未来的文章 本文翻译自 Memory ac ...

  7. linux内核多队列,Linux Kernel 中 Workqueue 使用系统默认队列和创建队列的方法

    关于workqueue,我们还是有很多话要说. 想必大家对workqueue相关的函数(schedule_work .queue_work.INIT_WORK.create_singlethread_ ...

  8. Intel 计划在Linux kernel中引入 User Interrupts,效率是eventfd的10倍

    文章目录 未来Eventfd的替代品 User Interrupts 详细介绍什么是 User Interrupts 底层是如何工作的? 内核管理相关的数据结构 User IPI 应用接口 具体的例子 ...

  9. linux kernel中的中断处理流程

    目录 1.linux kernel arm32的中断函数处理流程 (1).irq_handler宏 (2).arch_irq_handler_default 宏 (3).调用了asm_do_IRQ 2 ...

  10. linux kernel中local_irq_disable()、local_irq_enable()代码解读

    在armv8-arch64架构下,控制cpu是否响应IRQ,FIQ,SERROR,DEBUG中断,是由PSTATUS(daif寄存器)控制的. 在armv8-arch32或armv7架构下,控制cpu ...

最新文章

  1. CR--同事分享学习
  2. 剑指 Offer 43. 1~n整数中1出现的次数
  3. 378. Kth Smallest Element in a Sorted Matrix 有序矩阵中第K小的元素
  4. 10个Github热门Python库,非常实用!
  5. TCL电子港股暴涨10% 股价创5年新高
  6. java怎么这么难学6_Java难吗?
  7. oracle—新建用户
  8. CentOS6.5恢复误删除的文件
  9. php api 在线编辑导出,api在线管理,调试,文档生成工具之Apizza
  10. 前端优化 - 提高 Web 性能的 9 个技巧
  11. c语言个人日记本系统的设计,[设计]c语言程序课程设计日记本管理系统.doc
  12. 【经验分享】优麒麟上的硬盘读写性能测试
  13. 读书笔记 - 《资本幕后》
  14. c语言常见头文件大全,C语言头文件大全(free)
  15. 爬取微博评论并存入MySQL,并对评论进行情感分析以及词云的绘制
  16. 简单理解聚集索引和非聚集索引
  17. 什么是类?什么是对象?类与对象之间是什么关系?类的特性有哪些?
  18. [工具(前端)] 后台管理模板
  19. 阿里云物联网平台总结
  20. 简单的一个学生管理系统的实现(源码)

热门文章

  1. ASP.NET MVC 3.0(十二): MVC 3.0 使用自定义的Html控件
  2. 怎样把DataSet转换成ArrayList
  3. java 修饰关键字_java——关键字以及修饰属性
  4. mysql bing logo_mysqlbing log
  5. 尚硅谷mysql高级思维导图_幕布高级版,不花钱也能用!极简大纲笔记 | 一键生成思维导图...
  6. php excel数据导出
  7. Lucene.Net中 FSDirectory存储方式下一个 Document是如何得到的
  8. mybatis spring maven
  9. Android UI设计中一些不错的示例及第三方控件
  10. Java并发包学习--ReentrantLock