




已阅读5页,还剩4页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
6 1下半部 下半部的任务就是执行与中断处理密切相关但中断处理程序本身不执行的工作 对于在上半部和下半部之间划分工作 尽管不存在某种严格的规则 但还是有 一些提示可供借鉴 1 如果一个任务对时间非常敏感 将其放在中断处理程序中执行 2 如果一个任务和硬件相关 将其放在中断处理程序中执行 3 如果一个任务要保证不被其它中断打断 将其放在中断处理程序中执行 4 其它所有任务 考虑放在下半部执行 当我们开始尝试写自己的驱动程序的时候 读一下别人的中断处理程序和相应 的下半部会令你受益匪浅 现在的问题是 下半部具体放到以后的什么时候去做呢 下半部并不需要指明 一个确切时间 只要把这些任务推迟一点 让他们在系统不太繁忙并且中断恢 复后执行就可以了 通常下半部在中断处理程序一返回就会马上执行 下半部执行的关键在于当它 们运行的时候 允许响应所有中断 6 1 1为什么要用下半部 因为在中断处理程序运行的时候 当前的中断线会被屏蔽 如果一个处理程序 是 SA INTERRUPT 类型 它执行的时候会禁止所有本地中断 而且把本地中 断线全局屏蔽掉 再加上中断处理程序要与其它程序 甚至是其它的中断处理程序 异步执 行 具体放到以后什么时候去做呢 在这里 以后 仅仅用来强调不是 马上 而已 下半部并不需要指明一个确 切时间 只是把这些任务推迟一点 让它们在系统不太繁忙并且中断恢复后执 行就可以了 通常下半部在中断处理程序一返回就会马上执行 下半部执行的关键在于当它 们运行的时候 允许响应所有的中断 6 2软中断 软中断是用软件方式模拟硬件中断的概念 实现宏观上的异步执行效果 tasklet 也是基于软中断实现的 异步通知所基于的信号也类似于中断 硬中断是外部设备对 CPU 的中断 软中断通常是硬中断服务程序对内核的中断 信号则是由内核 或其它进程 对某个进程的中断 6 2 1软中断的实现 软中断是在编译期间静态分配的 不像 tasklet 那样能被动态的注册或去除 软 中断由 softirq action 结构表示 它定义在中 struct softirq action void action struct softirq action 待执行的函数 Void date 传递给函数的参数 在 kernel softirq c 中定义了一个包含有32个该结构体的数组 static strcut softirq action softirq vec 32 每个注册的软中断都占据该数组中的一 项 1 软中断处理程序 软中断处理程序 action 的函数原型如下 void softirq handler struct softirq action 当内核运行一个软中断处理程序的时候 它就会执行这个 action 函数 其唯一 的参数为指向相应的 softirq action 结构体的指针 一个软中断不会抢占另外一个软中断 实际上 唯一可以抢占软中断的是中断 处理程序 不过 其它的软中断 甚至是相同类型的软中断 可以在其它 处理器上同时执行 2 执行软中断 一个注册的软中断必须在被标记后才会执行 这被称作触发软中断 raising the softirq 通常 中断处理程序会在返回前标记它的软中断 使其在稍后被执行 软中断 被标记后 可以用 softirq pending 检查到这个标记并按照索引号将 softirq pending 的返回值的相应位置1 在合适的时刻 该软中断就会运行 在下列地方 待处理的软中断会被检查和 执行 在处理完一个硬中断以后 在 ksoftirqd 内核线程中 在那些显式检查和执行待处理的软中断的代码中 如网络子系统中 不管是用什么办法唤起 软中断都要在 do softirq 中执行 该函数很简单 如果有待处理的软中断 do softirq 会遍历每一个 调用它们的处理程序 软中断在 do softirq 中执行 do softirq 经过简化后的核心部分 u32 pending sofeirq pending cpu if pending struct softirq action h softirq vec softirq pending cpu 0 do if pending 调用 action 函数 h pending 1 while pending 6 2 2使用软中断 软中断保留给系统中对时间要求最严格以及最重要的下半部使用 内核定时器 和tasklets都是建立在软中断上的 如果你想加入一个新的软中断 首先要想想为什么用tasklet实现不了 tasklet可以动态生成 由于它们对加锁的 要求不高 所以使用起来也很方便 当然 对于时间要求养并能自己高效的完 成加锁工作的应用 软中断会是正确的选择 1 分配索引 在编译期间 可以通过中定义的一个枚举类型来静 态的声明软中断 2 注册处理程序 接着 在运行时通过调用open softirq 注册软件中断处理程序 该函数有三个参数 索引号 处理函数和data域存放的数值 例如网络子系统 通过以下方式注册自己的软中断 open softirq NET TX SOFTIRQ net tx action NULL open softirq NET TX SOFTIRQ net rx action NULL 软中断处理程序的执行的时候 允许响应中断 但自己不能睡眠 3 触发你的软中断 通过在枚举类型的列表中添加新项以及调用open softirq 进行注册以后 新的软 中断处理程序就能够运行 raise softirq 函数可以将一个软中断设置为挂起状态 让他在下次调用do softirq 函数时投入运行 一个例子 raise softirq NET TX SOFTIRQ 这会触发NET TX SOFTIRQ软中断 它的处理程序net tx action 就会在内核下一 次执行软中断时投入运行 该函数在触发一个软中断前要禁止中断 触发后再 恢复回原来的状态 在中断处理程序中触发软中断是最常见的形式 这样 内核在执行完中断处理 程序后 马上就会调用do softirq 于是软中断开始执行中断处理程序留给它去 完成的剩余任务 6 3 Tasklet tasklet 是利用软中断实现的一种下半部机制 它和进程没有任何关系 它和软 中断本质上很相似 行为表现也相近 但是 它的接口更简单 锁保护也要求 较低 软中断和 tasklet 怎样选择呢 通常你应该用 tasklet 软中断一般用的很少 它只在那些执行频率很高和连续 性要求很高的情况下才需要 而 tasklet 却有更广泛的用途 6 3 1 Tasklet 的实现 因为 tasklet 是通过软中断实现的 所以它本身也是软中断 1 tasklet 结构体 tasklet 由 tasklet struct 结构表示 每个结构体单独代表一个 tasklet 它在中定义 struct tasklet struct struct task struct next 指向链表中的下一个 tasklet unsigned long state tasklet 的状态 atomic t count 引用计数器 void func unsigned long tasklet 处理函数 unsigned long data 给 tasklet 处理函数的参数 结构体中的 func 成员是 tasklet 的处理程序 data 是它唯一的参数 state 成员只 能在0 TASKLET STATE SCHED 和 TASKLET STATE RUN 之间取值 TASKLET STATE SCHED 表明 tasklet 已经被调度 正准备投入运行 TASKLET STATE RUN 表示该 tasklet 正在运行 只有 count 为0时 tasklet 才 被激活 否则被允许 不允许执行 调度 tasklet 已调度的 tasklet 存放在两个单处理器数据结构 tasklet vec 和 task hi vec 中 它们都是由 tasklet struct 结构体构成的链表 链表中的每个 tasklet struct 代表 一个不同的 tasklet tasklet 是由 tasklet schedule 和 tasklet hi schedule 函数进行调度的 它们接受 一个指向 tasklet struct 结构的指针作为参数 Tasklet 的实现通过软中断来实现的 tasklet schedule 调度函数执行一些初始工 作 紧接着唤起 TASKLET SOFTIRQ 或 HI SOFTIRQ 软中断 这样在下一次 调用 do softirq 时就会执行 tasklet 那么 do softirq 函数什么时候执行呢 do softirq 会尽可能早的在下一个合适的时机执行 由于大部分 tasklet 和软 中断都是在中断处理程序中被设置成待处理状态 所以最近一个中断返回的时 候看起来就是执行 do softirq 的最佳时机 因为 TASKLET SOFTIRQ 和 HI SOFTIRQ 已经被触发了 所以 do softirq 会执 行相应的软中断处理程序 Tasklet action 和 Tasklet hi action 两个处理程序就是 tasklet 处理的核心 总结 所有的 Tasklets 都通过重复运用 TASKLET SOFTIRQ 或 HI SOFTIRQ 这两个软中断实现 当一个 tasklet 被调度时 内核就会唤起这两个软中断中的 一个 随后 该软中断会被特定的函数处理 执行所有已调度的 tasklet 这个函数保证同一时间里只有一个给定类别的 tasklet 会被执行 但其它不同类型的 tasklet 可以同时执行 所有这些复杂性都 被一个简洁的接口隐藏起来了 6 3 2使用 tasklet 声明你自己的 tasklet 可以静态创建 也可以动态创建 分别对应直接引用和间接引用 选择哪种方 式取决于你到底是有 或者是想要 一个对 tasklet 的直接引用还是间接引用 静态创建一个 tasklet 也就是有一个直接引用 使用下面中 定义的两个宏中的一个 DECLARE TASKLET name func data 实现了定义名称为 name 的 tasklet 并将其与 func 这个函数绑定 而传入这个函 数的参数为 data DECLARE TASKLET DISABLED name func data DECLARE TASKLET my tasklet my tasklet handler dev 运行代码实际上等价 于 struct tasklet struct my tasklet NULL 0 ATOMIC INIT 0 my tasklet handler dev 这样就创建了一个名为 my tasklet 处理程序为 tasklet handler 并且已经被 激活的 tasklet 还可以通过一个间接引用 一个指针 赋给一个动态创建的 tasklet struct 结构 的方式来初始化一个 tasklet Tasklet init t tasklet handler dev 动态而不是静态创建 编写你自己的 tasklet 处理程序 必须符合规定的函数类型 void tasklet handler unsigned long data 因为是靠软件中断实现 所以 tasklet 不能睡眠 这意味着你不能在 tasklet 中使 用信号量或者其它什么阻塞式的函数 调度你自己的 tasklet 通过调用 task schedule 函数并传递给它相应的 tasklet struct 的指针 该 tasklet 就会被调度以便执行 tasklet schedule 把 my tasklet 标记为挂起 下面我们看一下软中断和 tasklet 的异同 在前期准备工作上 首先要给软中断分配索引 而 tasklet 则要用宏对处理程序声明 在 给软中断分配索引后 还要通过 open softirq 函数来注册处理程序 这样看来 tasklet 是一步到位 直接到了处理函数 而软中断需要做更多工作 接下来 软中断要等待触发 raise softirq 或 raise softirq irqoff 而 tasklet 则是等待 tasklet schedule 和 tasklet hi schedule 对其进行调度 两者 虽然在命名上不同 但殊途同归 最终的结果都是等待 do softirq 去执行处理函数 即将下半部设置为待执行状态以便稍后执行 另外 在 tasklet 的 tasklet schedule 中 需要完成的动作之一便是唤起 触发 TASKLET SOFTIRQ 或 HI SOFTIRQ 软中断 说明 tasklet 仍然是基于软中断的 在进入 do softirq 之后 所做的工作仍然有所不同 不再论述 软中断和工作队列都是异步发生的 就是说 在中断处理返回的时候 6 4工作队列 工作队列 work queue 是另外一种将工作推后执行的形式 他和我们前面讨 论过的其他形式完全不同 工作队列可以把工作推后 交由一个内核线程去执 行 这个下半部总是会在进程上下文执行 这样 通过工作队列执行的代码能占尽进程上下文的所有优势 最重要的是工 作队列允许重新调度甚至是睡眠 如果你需要用一个可以重新调度的实体来执行你的下半部处理 你应该使用工 作队列 它是唯一能在进程上下文运行的下半部实现的机制 也只有它才可以 睡眠 这意味着你在你需要获得大量的内存时 在你需要获取信号量时 在你需要执行阻塞式的 IO 操作时 它都会非常有用 如果你不需要用一个内核线程来推后执行工作 那么就考虑使用 tasklet 吧 6 4 1工作队列的实现 工作队列子系统是一个用于创建内核线程的接口 通过它创建的进程负责执行 由内核其他部分排到队列里的其他任务 它创建的这些内核线程被称作工作者 线程 工作队列可以让驱动程序创建一个专门的工作者线程来处理需要推后的工作 不过 工作队列子系统提供了一个默认的工作者线程来处理这些工作 因此 工作队列最基本的表现形式就转变成了一个把需要推后执行的任务交给 特定的通用线程这样一个接口 表示线程的数据结构 工作者线程用 workqueue struct 结构表示 struct workqueue struct struct cpu workqueue struct cpu wq NR CPUS const char name struct list head list 该结构内是一个由 cpu workqueue struct 结构组成的数组 定义在 kernel workqueue c 中 数组的每一项对应一个系统中的处理器 每个工作者线程都对应这样的 cpu workqueue struct 结构体 cpu workqueue struct 是 kernel workqueue c 中的核心数据结构 struct cpu workqueue struct spinlock t lock 锁定以便保护该结构体 long romove sequeue 最近一个被加上的 下一个要运行的 long insert sequeue 下一个要加上的 wait queue head t more work wait queue head t work done struct workqueue struct wq 有关联的 workqueue struct 结构 task t thread 有关联的线程 int run depth run workqueue 循环深度 由此可以看出 每个工作者线程类型关联一个自己的 workqueue struct 在该结构体里 面 给每个线程分配一个 cpu workqueue struct 因而也就是给每个处理器分配一个 因为每个处理器都有一个该类型的线程 表示工作的数据结构 所有工作者线程都是用普通的内核线程实现的 它们都要执行 worker thread 函数 在 它初始化完以后 这个函数 worker thread 开始休眠 当有操作被插入到队列的时候 线程就会被唤醒 以便执行这些操作 当没有剩余的操作 时 它又会继续睡眠 工作用中定义的 work struct 结构体表示 struct work struct unsigned long pending 这个工作是否正在等待处理 struct list head entry l 连接所有工作的链表 void func void 处理函数 void wq data 内部使用 struct timer list timer 延迟的工作队列所用到的定时器 这些结构体被连接成链表 在每个处理器的每种类型的队列都对应这样一个链 表 当一个工作者线程被唤醒时 它会执行它的链表上的所有工作 当工作完毕时 他会将相应的 work struct 对象从链表中移去 当链表上不再有对 象的时候 它就会继续睡眠 6 4 2使用工作队列 1 创建推后的工作 首先要做的是实际创建一些需要推后执行的工作 可以通过 DECLARE WORK 在编译时 静态的创建该结构体 DECLARE WORK name void func void void data 这样就会静态的创建一个名为 name 处理函数为 func 参数为 data 的 work struct 结构体 也可以在运行时通过指针创建一个工作 INIT WORK struct work struct work void func void void data 这样就动态的初始化了一个由 work 指向的工作 2 工作队列的处理函数 原型是 void work handler void data 这个函数会由一个工作者线程执行 因此 函数会运行在进程上下文中 默认情况下 允 许响应中断 并且不持有任何锁 如果需要 函数可以睡眠 注意的是 尽管操作处理函数运行在进程上下文中 但它不能访问用户空间 因为内核线 程在用户空间没有相关的内存映射 通常在系统调用发生时 内核会代表用户空间的进程运行 此时它才能访问用户空间 也只有在此时它才会映射用 户空间的内存 3 对工作进行调度 现在工作已经创建 我们可以调度它了 要把给定工作的处理函数提交给默认的 events 工作线程 只需调用 schedule work work 马上就会被调度 一旦其所在的处理器上的工作者线程被唤醒 它就会被执行 4 刷新操作 刷新工作队列的函数就是确保在卸载模块之前 要确保一些操作已经执行完毕 了 该函数如下 Void flush scheduled work void 该函数会一直等待 直到队列中所有对象都被执行以后才返回 在等待所以待 处理的工作执行的时候 该函数会进入休眠状态 所以只能在进程上下文中使 用它 5 创建新的工作队列 当缺省的队列不能满足你的需要时 你应该创建一个新的工作队列和与之对应 的工作者线程
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- GB/T 23436-2025汽车风窗玻璃清洗液
- GB/T 7816-2025工业黄磷
- GB/T 26723-2025冷轧钛带卷
- JJF 2320-2025用水产品水效标识计量专项监督检查工作规范总则
- 2025春季内蒙古包头市中心医院引进高层次和紧缺急需人才招聘29人考前自测高频考点模拟试题及答案详解(夺冠系列)
- 2025年疾病预防控制及防疫服务项目发展计划
- 广本安全驾驶培训北京课件
- 2025年4月杭州市采荷中学编外教师招聘3人考前自测高频考点模拟试题附答案详解(黄金题型)
- 2025年嘉兴海宁市中心医院公开招聘高层次急需卫技人员4人考前自测高频考点模拟试题及完整答案详解1套
- 2025年河北唐山市丰润区选聘第二批事业编制医疗技术人员13名考前自测高频考点模拟试题附答案详解(完整版)
- 医学实验室安全培训
- 工贸企业安全生产标准化诊断报告编制指南
- 下浮率合同协议
- 2025年自考《艺术概论》考试复习题库(含答案)
- 人工智能深度学习概念与应用测试卷
- 小学道德与法治理论培训
- 离子检验-教案-
- GB/T 12643-2025机器人词汇
- 《酒店服务礼仪培训》课件
- Unit 5 Lesson 20 The Spring Festival Is Coming!(说课稿)-2024-2025学年冀教版(三起)英语五年级上册
- 药品采购与供应链管理
评论
0/150
提交评论