




已阅读5页,还剩6页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Linux 内核的中断机制分析内核的中断机制分析 一 中断的概念一 中断的概念 中断是指在 CPU 正常运行期间 由于内外部事件或由程序预先安排的事件引起的 CPU 暂时停止正 在运行的程序 转而为该内部或外部事件或预先安排的事件服务的程序中去 服务完毕后再返回去继续运 行被暂时中断的程序 Linux 中通常分为外部中断 又叫硬件中断 和内部中断 又叫异常 在实地址模式中 CPU 把内存中从 0 开始的 1KB 空间作为一个中断向量表 表中的每一项占 4 个 字节 但是在保护模式中 有这 4 个字节的表项构成的中断向量表不满足实际需求 于是根据反映模式切 换的信息和偏移量的足够使得中断向量表的表项由 8 个字节组成 而中断向量表也叫做了中断描述符表 IDT 在 CPU 中增加了一个用来描述中断描述符表寄存器 IDTR 用来保存中断描述符表的起始地 址 二 中断的请求过程二 中断的请求过程 外部设备当需要操作系统做相关的事情的时候 会产生相应的中断 设备通过相应的中断线向中断 控制器发送高电平以产生中断信号 而操作系统则会从中断控制器的状态位取得那根中断线上产生的中断 而且只有在设备在对某一条中断线拥有控制权 才可以向这条中断线上发送信号 也由于现在的外设越来 越多 中断线又是很宝贵的资源不可能被一一对应 因此在使用中断线前 就得对相应的中断线进行申请 无论采用共享中断方式还是独占一个中断 申请过程都是先讲所有的中断线进行扫描 得出哪些没有别占 用 从其中选择一个作为该设备的 IRQ 其次 通过中断申请函数申请相应的 IRQ 最后 根据申请结果 查看中断是否能够被执行 中断机制的核心数据结构是 irq desc 它完整地描述了一条中断线 或称为 中断通道 以下 程序源码版本为 linux 2 6 32 2 其中 irq desc 结构在 include linux irq h 中定义 typedef void irq flow handler t unsigned int irq struct irq desc desc struct irq desc unsigned int irq struct timer rand state timer rand state unsigned int kstat irqs ifdef CONFIG INTR REMAP struct irq 2 iommu irq 2 iommu endif irq flow handler t handle irq 高层次的中断事件处理函数 struct irq chip chip 低层次的硬件操作 struct msi desc msi desc void handler data chip 方法使用的数据 void chip data chip 私有数据 struct irqaction action 行为链表 action list unsigned int status 状态 unsigned int depth 关中断次数 unsigned int wake depth 唤醒次数 unsigned int irq count 发生的中断次数 unsigned long last unhandled 滞留时间 unsigned int irqs unhandled spinlock t lock 自选锁 ifdef CONFIG SMP cpumask var t affinity unsigned int node ifdef CONFIG GENERIC PENDING IRQ cpumask var t pending mask endif endif atomic t threads active wait queue head t wait for threads ifdef CONFIG PROC FS struct proc dir entry dir 在 proc 文件系统中的目录 endif const char name 名称 cacheline internodealigned in smp I Linux 中断的申请与释放 在 实现中断申请接口 request irq unsigned int irq irq handler t handler unsigned long flags const char name void dev 函数参数说明 unsigned int irq 所要申请的硬件中断号 irq handler t handler 中断服务程序的入口地址 中断发生时 系统调用 handler 这个函数 irq handler t 为自定义类型 其原型为 typedef irqreturn t irq handler t int void 而 irqreturn t 的原型为 typedef enum irqreturn irqreturn t enum irqreturn IRQ NONE 此设备没有产生中断 IRQ HANDLED 中断被处理 IRQ WAKE THREAD 唤醒中断 在枚举类型 irqreturn 定义在 include linux irqreturn h 文件中 unsigned long flags 中断处理的属性 与中断管理有关的位掩码选项 有一下几组值 define IRQF DISABLED 0 x00000020 中断禁止 define IRQF SAMPLE RANDOM 0 x00000040 供系统产生随机数使用 define IRQF SHARED 0 x00000080 在设备之间可共享 define IRQF PROBE SHARED 0 x00000100 探测共享中断 define IRQF TIMER 0 x00000200 专用于时钟中断 define IRQF PERCPU 0 x00000400 每 CPU 周期执行中断 define IRQF NOBALANCING 0 x00000800 复位中断 define IRQF IRQPOLL 0 x00001000 共享中断中根据注册时间判断 define IRQF ONESHOT 0 x00002000 硬件中断处理完后触发 define IRQF TRIGGER NONE 0 x00000000 无触发中断 define IRQF TRIGGER RISING 0 x00000001 指定中断触发类型 上升沿有效 define IRQF TRIGGER FALLING 0 x00000002 中断触发类型 下降沿有效 define IRQF TRIGGER HIGH 0 x00000004 指定中断触发类型 高电平有效 define IRQF TRIGGER LOW 0 x00000008 指定中断触发类型 低电平有效 define IRQF TRIGGER MASK IRQF TRIGGER HIGH IRQF TRIGGER LOW IRQF TRIGGER RISING IRQF TRIGGER FALLING define IRQF TRIGGER PROBE 0 x00000010 触发式检测中断 const char dev name 设备描述 表示那一个设备在使用这个中断 void dev id 用作共享中断线的指针 一般设置为这个设备的设备结构体或者 NULL 它是一个 独特的标识 用在当释放中断线时以及可能还被驱动用来指向它自己的私有数据区 来标识哪个设备在中 断 这个参数在真正的驱动程序中一般是指向设备数据结构的指针 在调用中断处理程序的时候它就会传 递给中断处理程序的 void dev id 如果中断没有被共享 dev id 可以设置为 NULL II 释放 IRQ void free irq unsigned int irq void dev id III 中断线共享的数据结构 struct irqaction irq handler t handler 具体的中断处理程序 unsigned long flags 中断处理属性 const char name 名称 会显示在 proc interreupts 中 void dev id 设备 ID 用于区分共享一条中断线的多个处理程序 struct irqaction next 指向下一个 irq action 结构 int irq 中断通道号 struct proc dir entry dir 指向 proc irq NN name 的入口 irq handler t thread fn 线程中断处理函数 struct task struct thread 线程中断指针 unsigned long thread flags 与线程有关的中断标记属性 thread flags 参见枚举型 enum IRQTF RUNTHREAD 线程中断处理 IRQTF DIED 线程中断死亡 IRQTF WARNED 警告信息 IRQTF AFFINITY 调整线程中断的关系 多个中断处理程序可以共享同一条中断线 irqaction 结构中的 next 成员用来把共享同一条中断线 的所有中断处理程序组成一个单向链表 dev id 成员用于区分各个中断处理程序 根据以上内容可以得出中断机制各个数据结构之间的联系如下图所示 三 中断的处理过程三 中断的处理过程 Linux 中断分为两个半部 上半部 tophalf 和下半部 bottom half 上半部的功能是 登记中断 当一个中断发生时 它进行相应地硬件读写后就把中断例程的下半部挂到该设备的下半部执行队列中去 因此 上半部执行的速度就会很快 可以服务更多的中断请求 但是 仅有 登记中断 是远远不够的 因 为中断的事件可能很复杂 因此 Linux 引入了一个下半部 来完成中断事件的绝大多数使命 下半部和 上半部最大的不同是下半部是可中断的 而上半部是不可中断的 下半部几乎做了中断处理程序所有的事 情 而且可以被新的中断打断 下半部则相对来说并不是非常紧急的 通常还是比较耗时的 因此由系统 自行安排运行时机 不在中断服务上下文中执行 中断号的查看可以使用下面的命令 cat proc interrupts Linux 实现下半部的机制主要有 tasklet 和工作队列 小任务 tasklet 的实现 其数据结构为 struct tasklet struct 每一个结构体代表一个独立的小任务 定义如下 struct tasklet struct struct tasklet struct next 指向下一个链表结构 unsigned long state 小任务状态 atomic t count 引用计数器 void func unsigned long 小任务的处理函数 unsigned long data 传递小任务函数的参数 state 的取值参照下边的枚举型 enum TASKLET STATE SCHED 小任务已被调用执行 TASKLET STATE RUN 仅在多处理器上使用 count 域是小任务的引用计数器 只有当它的值为 0 的时候才能被激活 并其被设置为挂起状态时 才能够被执行 否则为禁止状态 I 声明和使用小任务 tasklet 静态的创建一个小任务的宏有一下两个 define DECLARE TASKLET name func data struct tasklet struct name NULL 0 ATOMIC INIT 0 func data define DECLARE TASKLET DISABLED name func data struct tasklet struct name NULL 0 ATOMIC INIT 1 func data 这两个宏的区别在于计数器设置的初始值不同 前者可以看出为 0 后者为 1 为 0 的表示激活状 态 为 1 的表示禁止状态 其中 ATOMIC INIT 宏为 define ATOMIC INIT i i 即可看出就是设置的数字 此宏在 include asm generic atomic h 中定义 这样就创建了一个名为 name 的小任务 其处理函数为 func 当该函数被调用的时候 data 参数就被传递给它 II 小任务处理函数程序 处理函数的的形式为 void my tasklet func unsigned long data 这样 DECLARE TASKLET my tasklet my tasklet func data 实现了小任务名和处理函数的绑定 而 data 就 是函数参数 III 调度编写的 tasklet 调度小任务时引用 tasklet schedule 这个调度函数放在中断处理的上半部处理函数中 这样中断申请的时候调用处理函数 即 irq handler t handler 后 转去执行下半部的小任务 如果希望使用 DECLARE TASKLET DISABLED name function data 创建小任务 那么在激活的 时候也得调用相应的函数被使能 tasklet enable struct tasklet struct 使能 tasklet tasklet disble struct tasklet struct 禁用 tasklet tasklet init struct tasklet struct void func unsigned long unsigned long 当然也可以调用 tasklet kill struct tasklet struct 从挂起队列中删除一个小任务 清除指定 tasklet 的可调度位 即不允许调度该 tasklet 使用 tasklet 作为下半部的处理中断的设备驱动程序模板如下 定义 tasklet 和下半部函数并关联 void my do tasklet unsigned long DECLARE TASKLET my tasklet my tasklet func 0 中断处理下半部 void my do tasklet unsigned long 编写自己的处理事件内容 中断处理上半部 irpreturn t my interrupt unsigned int irq void dev id tasklet schedule 设备驱动模块的卸载函数 void exit xxx exit void 释放中断 free irq my irq my interrupt 工作队列的实现 工作队列 work struct 结构体 位于 include linux workqueue h typedef void work func t struct work struct work struct work struct atomic long t data 传递给处理函数的参数 define WORK STRUCT PENDING 0 这个工作是否正在等待处理标志 define WORK STRUCT FLAG MASK 3UL define WORK STRUCT WQ DATA MASK WORK STRUCT FLAG MASK struct list head entry 连接所有工作的链表 work func t func 要执行的函数 ifdef CONFIG LOCKDEP struct lockdep map lockdep map endif 这些结构被连接成链表 当一个工作者线程被唤醒时 它会执行它的链表上的所有工作 工作被执 行完毕 它就将相应的 work struct 对象从链表上移去 当链表上不再有对象的时候 它就会继续休眠 可以通过 DECLARE WORK 在编译时静态地创建该结构 以完成推后的工作 define DECLARE WORK n f struct work struct n WORK INITIALIZER n f 而后边这个宏为一下内容 define WORK INITIALIZER n f data WORK DATA INIT entry 这会动态地初始化一个由 work 指向的工作队列 并将其与处理函数绑定 宏原型为 define INIT WORK work func do static struct lock class key key work data atomic long t WORK
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年中央一号文件自测50题【答案+解析】
- 出纳安全培训内容课件
- 衡水金卷四省(四川云南)高三联考9月联考政治(含答案)
- 涉密信息系统集成资质保密知识测试题库题库(含答案)
- 2025年面条买卖合同
- 道教入学考试面试问题及答案
- 思瑞浦招聘笔试题库2025
- 2025年农村私人房屋买卖合同范本
- 2025合同范本:计算机硬件采购合同样本
- 2025年上海房屋租赁合同范本版
- GB/T 42381.8-2023数据质量第8部分:信息和数据质量:概念和测量
- 中国传统故事英文九色鹿二篇
- 设施蔬菜生产机械化技术
- LY/T 1821-2009林业地图图式
- JJF 1272-2011阻容法露点湿度计校准规范
- 液压与气压传动 第2版 马振福 高职课件0、1新
- 危化品安全管理学习课件
- SY∕T 7298-2016 陆上石油天然气开采钻井废物处置污染控制技术要求
- 突发事件处理记录表(标准范本)
- 磁敏传感器(品) 课件
- 美国航空无线电设备公司标准ARINC
评论
0/150
提交评论