




已阅读5页,还剩3页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Linux 中断1 介绍我们知道,处理器的处理速度比硬件来说要快上N个数量级,那么由处理器向硬件发出请求并等待回应的办法显然是不可取的,在这期间处理器浪费了大量的时间。这些时间应该被用来处理其他的事务。轮询可能是解决办法之一,但显然这样的办法也会让处理器做大量的无用功。最好的办法,就是让硬件在需要的时候才向内核发出信号,然后处理器去响应硬件的请求。这就是中断机制。1.1 什么是中断当硬件需要和处理器通信时,会产生一个电信号(即中断信号),并发往处理器,处理器收到后,会告诉OS,然后由OS进行后续处理。每一种硬件设备都有其专门的中断值,OS得以通过这个来进行区分,到底是哪个设备发生了中断。这些中断值又被称为中断请求(IRQ)当然有的IRQ是动态分配的。其实OS关注的并不是某个设备一定要产生某个特定的IRQ,而是一个特定的IRQ要和一个特定的设备有映射的关系,而且OS需要知道这种关系。这就表明,即便是IRQ在多个设备之间进行共享也是可以的,只要OS能够知道这些映射关系,并且能够有办法区分某一个时刻产生中断的设备是哪一个即可。1.2 中断处理程序中断处理程序,顾名思义,自然就是发生中断时,需要调用的处理函数。特点:、不是每设备一个处理程序,而是每中断一个处理程序一个设备可以有多个中断处理程序。、运行于特殊的上下文中:中断上下文、一般的中断处理程序,都会关中断,考虑到中断随时都有可能发生,处理程序应当尽可能的高效、一般中断处理程序都是要和硬件打交道的1.3 中断上下文1.3.1 回忆进程上下文、 对内核而言,处于进程上下文表明内核处于这样一种模式:进程在执行(系统调用或者运行内核线程)、 可以通过current宏关联当前进程、 进程以进程上下文的形式关联内核,使得在进程上下文中可以睡眠,也可以调用调度程序。1.3.2 中断上下文中断上下文,则和进程上下文几乎完全相反:和进程无关、和current宏无关不能睡眠、不能调用会导致睡眠的函数。另外,处于中断上下文的代码,应当迅速、简洁,尽量把工作放到下半部中去完成。关于中断使用的堆栈:2.6的内核之前,中断没有自己的堆栈,而是与被中断的内核线程共享该线程的堆栈(2页)。2.6之后,内核增加了一个选项:每个内核线程只提供一页内存,这减轻了内存的压力,也同时促使中断被分离了出来:每处理器一页,称为中断栈1.4 中断的实现机制Linux中,中断的处理机制是依赖于体系结构的(处理器、中断控制器、体系结构的设计、机器本身)。下图是中断的路由1.5 关于中断的下半部我们为什么需要下半部?因为我们要把中断处理中需要做的工作区分开来:中断处理程序中,只处理那些有严格时间限制的工作,比如复位硬件,对中断进行应答等。而那些可以拖到后面做的,或者说有可能睡眠的处理,都应当放到下半部去处理这样做的目的很显然,就是让中断处理程序尽可能的简洁明快在适当的时机,下半部会开中断执行2 中断控制为什么要控制中断?控制中断的原因,说到底还是为了要进行同步。通过禁止中断,可以确保该中断不会抢占当前运行的代码。禁止中断还可以禁止内核抢占。需要注意的是,中断都是对每处理器而言(中断堆栈),也就是说,禁止中断并不能够保证自己使用的数据不会被其他处理器的并发进程所访问到。因此如果在使用某些全局的数据时,需要考虑对其进行加锁保护。即:锁提供机制,防止来自其他处理器(当然也可以是本处理器)的并发访问,中断提供机制,防止来自其他中断处理程序的并发访问。2.1 禁止和激活中断这里需要注意的是,内核提供两类接口:禁止/激活中断,保存/恢复中断状态。前者比较傻瓜,会无条件的禁止/激活中断,这需要使用者对当前的中断状态十分确定。而后者则相对更容易使用,免去了判断另外关于cli()与sti(): 在2.5版本之前的内核,提供“禁止所有处理器上的中断”这样的功能,现在已经去掉了,需要开发人员用锁来避免并发。这么做的好处是,是的代码更加流线化,不会簇拥成团。而且使用粒度更细的锁,会比全局锁要效率高。2.2 禁止指定中断线我们当然不用禁止全局的中断,有时候禁止某一条中断线就可以了,这是指:凡是在该中断线上产生的中断,都将不会报告给处理器。一般对于有多个中断处理程序共享的中断线,并不建议使用这个功能,因为这会导致这条线上的其他的设备无法传递中断。2.3 中断系统的状态有时候我们需要判断代码所处的状态:是否在中断上下文中。因为有些操作是只有在进程上下文中才能够进行的,比如睡眠。系统提供接口,来判断中断是否被禁止、是否处于中断上下文、是否正在执行中断处理程序。3 下半部一般的中断处理都会分为两个部分,前面讲到的中断处理程序只是所谓的上半部,这是系统处理中断不可或缺的一部分。但是由于中断处理程序本身的局限,仅靠上半部是无法高效的处理系统的所有中断的,这就需要下半部来提供支持。3.1 为什么需要下半部3.1.1 上半部的局限、 中断处理程序异步执行,且有可能打断其他代码,包括其他的中断处理程序、 中断处理程序执行时,会禁止该中断同级的其他中断,甚至禁止全局所有中断、 往往需要对硬件进行操作、 中断处理程序在中断上下文中运行,有很多限制以上几点,就要求中断处理程序不仅要简洁、高效,而且对于阻塞这种行为也是不能支持的,这就导致上半部的限制很多。3.1.2 使用下半部、 处理中断时,工作推后到下半部的原因,就是为了突破上面提到的局限性,要尽可能的将那些可以推后执行的工作都放到下半部,提高系统的响应速度、 下半部何时被调用?这个跟中断处理选择用何种下半部机制有关,可以是推后一段时间,也可以是通过定时器、 下半部的特点:在进行处理的时候,随时都有可能响应中断、 除了Linux,很多其他的操作系统也采用了同样的机制3.2 下半部介绍、 下半部的实现方式,在2.6的内核中,有3种:软中断、tasklet、工作队列。软中断用的比较少,只有有限的几种使用场景,更多的是使用tasklet、 内核定时器,同样也能够将工作推后一段时间(精确的)进行3.3 软中断3.3.1 软中断的实现、 软中断是在内核编译期间静态分配的,不能够动态裁剪。系统定义了一个32个元素的数组,但是目前只用到了寥寥几个。多数还是通过tasklet来实现、 软中断不会抢占相同处理器上的其他软中断,软中断会被中断给打断、 软中断的执行:中断处理程序在返回之前,将对应的软中断进行标记(触发软中断),然后系统会在合适的时机检查该标记,并执行软中断(从中断处理程序返回时、在ksoftirqd内核线程中、显示检查与处理软中断的代码)。3.3.2 软中断的使用、 软中断是给系统中对时间要求最严格,以及最重要的下半部来使用。目前只有两个子系统在使用:网络子系统以及SCSI子系统、 执行软中断处理程序的时候,能够相应中断,但自己不能睡眠、 软中断虽然可以禁止本处理器上的同类软中断,但是对不同处理器的同类软中断是没有限制的(这就意味着潜在的数据并发访问)。因此我们需要考虑同步(加锁、或者使用每处理器数据)、 对于软中断,只有执行频率很高,连续性要求很高的情况下,才考虑使用3.4 Tasklet3.4.1 tasklet的实现、 tasklet的实现是基于软中断的,所以其本身也是软中断、 tasklet可以静态定义,也可以动态创建3.4.2 tasklet的调度、 已触发的tasklet,分为两类:普通优先级 / 高优先级的软中断(前面提到过)、 Tasklet调度函数首先检查状态,若已经被调度过一次,则立刻返回、 保存中断状态,禁止本地中断、 设置tasklet需要处理的标记并开中断、 在合适的时候,执行do_softirq(),通过内部调用,获取对应状态的tasklet链表,对每一个tasklet进行处理:如果是RUN状态,则跳过同一时间内,同样的tasklet只有一个能够执行,否则标记为RUN并执行之,执行后取消RUN的状态标记总的来说:每一个tasklet都重复设置HI_SOFTIRQ / TASKLET_SOFTIRQ这2个软中断进行,当一个tasklet被调度时,某一类软中断被唤醒并被特殊的处理函数进行处理,该函数处理执行所有被触发的tasklet(不同类型的tasklet可以同时执行,同类的则只能有一个)3.4.3 tasklet的使用、 tasklet的使用比较简单,步骤就是创建(静/动)、注册自己的处理函数、调度、或者从待运行链表中删除、 注意你的处理函数中,不应该使用信号量,不应该进行睡眠、 注意对和其他类型tasklet、软中断等进行了共享的数据进行加锁保护3.4.4 关于ksoftirqd内核线程问题描述:软中断与tasklet(实际上也是软中断),被触发的频率实际上是相当高的,而且软中断自己还会重新触发软中断(比如网络子系统),这么一来就很有可能导致用户空间甚至得不到处理器时间,长时间处于饥饿状态两个简单的方案:一是只要还有被触发的待处理的软中断,本次执行就要负责处理,中途触发的软中断也要处理。二是不处理重新触发的软中断,等到下一次执行。上述两个方案的不足:前者在系统负载很高的时候,软中断会被不停的触发,以至于用户空间几乎都得不到响应;后者虽然保证了用户进程不会挨饿,但是却牺牲了软中断的性能,在系统空闲时没有充分利用系统资源ksoftirqd/n 线程:这组内核线程是上述两种方案的最后折中产物,该线程每处理器一个,并以最低nice值运行。内核在每次执行软中断时,都不会处理重新触发的软中断,该工作由ksoftirqd线程进行。当负载较高时,其他线程由于优先级较高,自然能够获取处理器资源;相反当系统较空闲时,ksoftirqd线程能被立刻调度,那么软中断也就可以被立刻执行。下面是ksoftirqd:3.5 工作队列3.5.1 原理与实现、 工作队列是内核提供的第三种下半部机制,与前两种有所不同,最主要的区别就是工作队列将工作推后给一个内核线程events/n去执行。意味着可以进行睡眠,意味着当需要信号量、阻塞、大量内存时,工作队列应该是你的首选、 每个处理器都会有一个工作者线程,也同时对应一个workque_struct,用户将需要进行处理的工作挂到工作队列中,当线程被调用,则会判断工作队列是否为空,为空则睡眠,否则执行队列中的任务、 工作者队列一般只有系统默认的event类型,对应到系统中是每个处理器一个events线程。如果要增加工作队列类型,那么会导致增加处理器个数个内核线程,所以增加类型一定要慎重3.5.2 使用工作队列、 可以通过静态方式(DECLARE_WORK)或者动态方式(INIT_WORK)定义自己的工作队列、 处理函数虽然运行在进程上下文,但不应该访问用户空间的数据、 默认情况下,处理函数允许响应中断,不持有任何锁,可以在需要的时候进行睡眠、 调度工作队列时,可以简单指明需要调度,也可以具体指明经过多少时钟节拍后再进行调度。同时,内核也提供了刷新工作队列的接口(睡眠等待所有工作完成),有时候会需要这样的刷新操作来确保不再有待处理的工作、 如果有需要,可以定义新的工作队列类型3.6 下半部之间加锁、 不同类tasklet之间需要考虑数据的同步、 软中断之间需要考虑数据同步、 进程上下文与下半部共享数据,在访问数据前,要禁止下半部处理,并获取锁、 中断上下文与下半部共享数据,在访问数据前,要禁止中断,并获取锁、 工作队列由于可能睡眠,也需要考虑数据同步4 实现自己的中断我们可以在系统中添加属于自己的中断处理,包括中断处理程序以及可能需要的下半部。4.1 注册中断处理程序在编写中断处理程序之前,需要申请中断线,并且注册自己的处理函数。这里需要注意的有:中断线是可以多个设备共享的,当共享中断线时,通过设备id来进行区分;初始化硬件和注册中断处理函数的顺序要对,避免在硬件初始化之前就开始执行中断处理程序。4.2 编写中断处理程序、 通常标记为static、 至少也要通知硬件,中断已经收到、 对于较复杂的设备,可能需要发送、接受数据,甚至做一些扩展工作、 扩展工作应当尽量放到下半部、 一般会在处理程序中先关中断,所以可以不用考虑重入(中断的嵌套,只会是不同类型的中断)、 如果访问其他共享数据,比如和其他高优先级中断处理程序共享的数据时,要考虑同步问题、 多个设备可以共享中断线,当产生中断时,内核会依次调用注册在该中断线
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 日语试题分类及答案
- 仓库考试试题及答案
- 中信青岛面试题及答案
- 员工离岗测试题及答案
- 2025年国家电梯作业人员T证考试练习题库(含答案)
- 静脉输液考试测试卷附答案
- 2024年下半年全国事业单位联考A类《综合应用能力》真题(附答案)
- 北京特产工艺品知识培训课件
- 消毒消毒考试题及答案
- 电工(初级工)模拟练习题与参考答案
- 中国慢性肾脏病患者高血压管理指南(2023年版)解读
- TCALC 003-2023 手术室患者人文关怀管理规范
- 学校幼儿园食品安全培训课件
- 水利工程中常见机电设备的基本知识
- 家具行业常用中英文对照
- 英语四六级词汇汇总(带音标+免费下载)
- 插板机安全操作规程
- 铭复乐IV期临床方案介绍
- 并购贷款业务培训
- 建设集团有限公司安全生产管理制度汇编
- 交通信号控制系统检验批质量验收记录表
评论
0/150
提交评论