您好、欢迎来到现金彩票网!
当前位置:彩之网 > 中断机制 >

中断处理的tasklet(小任务)机制和workqueue(工作队列)机制

发布时间:2019-07-25 07:15 来源:未知 编辑:admin

  以避免嵌套而使中断控制复杂化。但是,中断是一个随机事件,它随时会到来,如果关中断的时间太长,就不能及时响应其他的中断请求,从而造成中断的丢失。因此,Linux内核的目标就是尽可能快的处理完中断请求,尽其所能把更多的处理向后推迟。例如,假设一个数据块已经达到了网线,当中断控制器接受到这个中断请求信号时,内核只是简单地标志数据到来了,然后让处理器恢复到它以前运行的状态,其余的处理稍后再进行(如把数据移入一个缓冲区,接受数据的进程就可以在缓冲区找到数据)。因此,内核把中断处理分为两部分:上半部(tophalf)和下半部(bottomhalf),上半部(就是中断服务程序)内核立即执行,而下半部(就是一些内核函数)留着稍后处理,

  首先,一个快速的“上半部”来处理硬件发出的请求,它必须在一个新的中断产生之前终止。通常,除了在设备和一些内存缓冲区(如果你的设备用到了DMA,就不止这些)之间移动或传送数据,确定硬件是否处于健全的状态之外,这一部分做的工作很少。

  下半部运行时是允许中断请求的,而上半部运行时是关中断的,这是二者之间的主要区别。

  但是,内核到底什时候执行下半部,以何种方式组织下半部?这就是我们要讨论的下半部实现机制,这种机制在内核的演变过程中不断得到改进,在以前的内核中,这个机制叫做bottomhalf(简称bh),在2.4以后的版本中有了新的发展和改进,改进的目标使下半部可以在多处理机上并行执行,并有助于驱动程序的开发者进行驱动程序的开发。下面主要介绍常用的小任务(Tasklet)机制及2.6内核中的工作队列机制。

  这里的小任务是指对要推迟执行的函数进行组织的一种机制。其数据结构为tasklet_struct,每个结构代表一个独立的小任务,其定义如下:

  结构中的func域就是下半部中要推迟执行的函数,data是它唯一的参数。

  State域的取值为TASKLET_STATE_SCHED或TASKLET_STATE_RUN。TASKLET_STATE_SCHED表示小任务已被调度,正准备投入运行,TASKLET_STATE_RUN表示小任务正在运行。TASKLET_STATE_RUN只有在多处理器系统上才使用,单处理器系统什么时候都清楚一个小任务是不是正在运行(它要么就是当前正在执行的代码,要么不是)。

  Count域是小任务的引用计数器。如果它不为0,则小任务被禁止,不允许执行;只有当它为零,小任务才被激活,并且在被设置为挂起时,小任务才能够执行。

  1. 声明和使用小任务大多数情况下,为了控制一个寻常的硬件设备,小任务机制是实现下半部的最佳选择。小任务可以动态创建,使用方便,执行起来也比较快。

  我们既可以静态地创建小任务,也可以动态地创建它。选择那种方式取决于到底是想要对小任务进行直接引用还是一个间接引用。如果准备静态地创建一个小任务(也就是对它直接引用),使用下面两个宏中的一个:

  这两个宏都能根据给定的名字静态地创建一个tasklet_struct结构。当该小任务被调度以后,给定的函数func会被执行,它的参数由data给出。这两个宏之间的区别在于引用计数器的初始值设置不同。第一个宏把创建的小任务的引用计数器设置为0,因此,该小任务处于激活状态。另一个把引用计数器设置为1,所以该小任务处于禁止状态。例如:

  这样就创建了一个名为my_tasklet的小任务,其处理程序为tasklet_handler,并且已被激活。当处理程序被调用的时候,dev就会被传递给它。

  由于小任务不能睡眠,因此不能在小任务中使用信号量或者其它产生阻塞的函数。但是小任务运行时可以响应中断。

  3. 调度自己的小任务通过调用tasklet_schedule()函数并传递给它相应的tasklt_struct指针,该小任务就会被调度以便适当的时候执行:

  在小任务被调度以后,只要有机会它就会尽可能早的运行。在它还没有得到运行机会之前,如果一个相同的小任务又被调度了,那么它仍然只会运行一次。

  可以调用tasklet_disable()函数来禁止某个指定的小任务。如果该小任务当前正在执行,这个函数会等到它执行完毕再返回。调用tasklet_enable()函数可以激活一个小任务,如果希望把以DECLARE_TASKLET_DISABLED()创建的小任务激活,也得调用这个函数,如:

  也可以调用tasklet_kill()函数从挂起的队列中去掉一个小任务。该函数的参数是一个指向某个小任务的tasklet_struct的长指针。在小任务重新调度它自身的时候,从挂起的队列中移去已调度的小任务会很有用。这个函数首先等待该小任务执行完毕,然后再将它移去。

  从这个例子可以看出,所谓的小任务机制是为下半部函数的执行提供了一种执行机制,也就是说,推迟处理的事情是由tasklet_handler实现,何时执行,经由小任务机制封装后交给内核去处理。

  工作队列(work queue)是另外一种将工作推后执行的形式,它和前面讨论的tasklet有所不同。工作队列可以把工作推后,交由一个内核线程去执行,也就是说,这个下半部分可以在进程上下文中执行。这样,通过工作队列执行的代码能占尽进程上下文的所有优势。最重要的就是工作队列允许被重新调度甚至是睡眠。

  那么,什么情况下使用工作队列,什么情况下使用tasklet。如果推后执行的任务需要睡眠,那么就选择工作队列。如果推后执行的任务不需要睡眠,那么就选择tasklet。另外,如果需要用一个可以重新调度的实体来执行你的下半部处理,也应该使用工作队列。它是唯一能在进程上下文运行的下半部实现的机制,也只有它才可以睡眠。这意味着在需要获得大量的内存时、在需要获取信号量时,在需要执行阻塞式的I/O操作时,它都会非常有用。如果不需要用一个内核线程来推后执行工作,那么就考虑使用tasklet。

  如前所述,我们把推后执行的任务叫做工作(work),描述它的数据结构为work_struct,这些工作以队列结构组织成工作队列(workqueue),其数据结构为workqueue_struct,而工作线程就是负责执行工作队列中的工作。系统默认的工作者线程为events,自己也可以创建自己的工作者线程。

  这些结构被连接成链表。当一个工作者线程被唤醒时,它会执行它的链表上的所有工作。工作被执行完毕,它就将相应的work_struct对象从链表上移去。当链表上不再有对象的时候,它就会继续休眠。

  要使用工作队列,首先要做的是创建一些需要推后完成的工作。可以通过DECLARE_WORK在编译时静态地建该结构:

  这样就会静态地创建一个名为name,待执行函数为func,参数为data的work_struct结构。

  这个函数会由一个工作者线程执行,因此,函数会运行在进程上下文中。默认情况下,允许响应中断,并且不持有任何锁。如果需要,函数可以睡眠。需要注意的是,尽管该函数运行在进程上下文中,但它不能访问用户空间,因为内核线程在用户空间没有相关的内存映射。通常在系统调用发生时,内核会代表用户空间的进程运行,此时它才能访问用户空间,也只有在此时它才会映射用户空间的内存。

  现在工作已经被创建,我们可以调度它了。想要把给定工作的待处理函数提交给缺省的events工作线程,只需调用

  work马上就会被调度,一旦其所在的处理器上的工作者线程被唤醒,它就会被执行。

  有时候并不希望工作马上就被执行,而是希望它经过一段延迟以后再执行。在这种情况下,可以调度它在指定的时间执行:

  这时,&work指向的work_struct直到delay指定的时钟节拍用完以后才会执行。

  一、中断处理机制     中断是一个随机事件,因此如果关中断的时间过长,CPU就不能及时的响应其他的中断请求,从而造成中断的丢失。因此,Linux内核的目标就是尽可能快的处理完中断请求,尽可能的把更多...博文来自:HelloBirthday的博客

  1:内核定时器:在内核中有系统自带的定时器,达到一定的时间就可以进行一个操作,这个和单片机中的定时器中断一样。包含头文件是Timer.h(\include\linux)结构体是timer_listst...博文来自:感觉身体被掏空

  workqueue与tasklet功能相似,都是让某个函数在将来被调用。但是两者件也有一些区别:tasklet在软件中断上下文中运行,tasklet代码必须是原子的。工作队列在一个特殊的内核线程的上下...博文来自:Hansomewang的博客

  对于操作系统来说,中断的实现和裸机代码是不一样的,对于裸机代码来说,它的处理过程更符合下面这个流程,我们在编写裸板驱动代码的时候,一般处理的是硬件中断,而且中断号也是硬件中断号,这个中断号是和CPU寄...博文来自:奔跑的路

  回顾:linux内核混杂设备。特点:主设备号由内核分配好,主设备号为10;内核通过次设备来区分各个混杂设备。数据结构:structmiscdevice{intminor;//MISC_DYNAMIC_...博文来自:我的专栏

  内核工作队列概述工作队列(workqueue)是另外一种将工作推后执行的形式,工作队列可以把工作推后,交由一个内核线程去执行,也就是说,这个下半部分可以在进程上下文中执行,最重要的就是工作队列允许被重...博文来自:z961968549的博客

  一引入工作队列(workqueue)之前聊过Linux中断机制分为上半部中断(硬中断)和下半部,顶半部中断用于完成比较紧急的功能,往往只是简单的读取寄存器中的中断状态,并在清除中断标志后,启动下半部,...博文来自:大神笔记

  在第一个教程中,我们通过一个命名队列来发送消息和接受消息。在这一节,我们将创建一个工作...博文来自:whywordonly的专栏

  工作队列(WorkQueue)工作队列是一种企业级任务管理协同机制。在RPA领域,工作队列通常指将以业务视角出发的单一工作任务放入工作队列池,再按需执行的过程。这些单一工作任务,往往是指每一笔工单,每...博文来自:dev_kex的博客

  前两篇文章介绍了中断的原理和基本框架,但是实际使用过程中会用到中断上下文的编程方法,这里介绍work_queue.我使用的硬件是imx6q,原理都一样。原来的beep引脚是output模式,电路上把它...博文来自:不积硅步,无以至千里

  工作队列是内核用于进行延后工作的一种方式。当然驱动模块中使用之前提到的kernelthread就可以完成延后工作了,但是如果每个驱动模块都创建自己的kernelthread,那么内核线程数量过多,这会...博文来自:weixin_39821531的博客

  把work_struct加入到工作队列workqueue的API在系列文章1有介绍,这些API虽然用法不一,但是最终都会调用__queue_work()函数来进行实际加入操作,比如API:queue_...博文来自:linux从业者

  softirq tasklet 工作队列 执行上下文 延后的工作运行于中断上下文 延后的工作运行于中断上下文 延后的工作运行于进程上下文 可重用 可以在不同的CPU上同时运...博文来自:weixin_39821531的博客

  【版权声明:尊重原创,转载请保留出处:shallnet,文章仅供学习交流,请勿用于商业用途】     tasklet是利用软中断实现的一种下半部机制。tasklet相比于软...博文来自:程序猿的挨踢人生

  概述:等待队列、工作队列、Tasklet都是linux驱动很重要的API,下面主要从用法上来讲述如何使用API.应用场景:等待队列(waitqueue)linux驱动中,阻塞一般就是用等待队列来实现,...博文来自:子木

  我正在学习Zephyr,一个很可能会用到很多物联网设备上的操作系统,如果你也感兴趣,可点此查看帖子zephyr学习笔记汇总。1前言工作队列是一个内核对象,它使用专用线程以先进先出的方式处理工作项目。通...

  一、Tasklets机制基础知识点1、Taklets机制概念   Tasklets机制是linux中断处理机制中的软中断延迟机制。通常用于减少中断处理的时间,将本应该是在中断服务程序中完成的任务转化成...

  JDK可以创建使用Executors创建5种类型的线程池Executors.newCachedThreadPool();该方法返回一个可根据实际情况调整线程数量的线程池。线程池的线程数量不确定,但若有...

  1、综述基于硬件工程师的提出的一个测试需求:每隔5秒钟拉高PA的使能脚,间隔5秒钟再拉低PA使能脚(这里的PA指的是poweramplifier-gt;即功率放大器的意思)换句话说,就是播放...

  STM32具有极其强大的中断功能,不再赘述,只说明中断使用的方法步骤,以按键中断为例1、初始化需要连接到EXTI的GPIO,方法与所有GPIO初始化方法一致,开时钟,配置结构体,写入寄存器2、初始化E...

  好帖子:工作队列 为什么使用workqueue? 在内核代码中,经常希望延缓部分...

  一、中断的顶半部和底半部   设备的中断会打断内核中进程的正常调度和运行,而系统对更高吞吐率的追求势必要求中断服务程序尽可能地短小精悍。但是,这个良好的愿望往往与现实并不吻合。在大多数真实的系统中,当...

  前言前面讲了linux中断编程:顶半部、底半部中断顶半部:做紧急的,耗时短的事情,同时还启动中断底半部(如果有)。中断底半部:做耗时的事情,这个事件可以被中断实现方法:tasklet、工作队列、软中断...

  1.事件循环JavaScript引擎并不是独立运行的,它运行在宿主环境中,对多数开发者来说通常就是Web浏览器。经过最近几年的发展,JavaScript已经超出了浏览器的范围,进入了其他环境,比如通过...

  x86的启动进入BIOS    x86在上电启动后,和所有处理器一样,执行一条固定位置的指令。其位置是CS=FFFF000H,EIP=0000FFF0H。此时运行在实模式下,因此CS:EIP得到的即为...

  LDD3:工作队列是,表面上看,类似于taskets;它们允许内核代码来请求在将来某个时间调用一个函数.但是,有几个显著的不同在这2个之间,包括:(1)tasklet在软件中断上下文中运行的结果是所有...

  各位大神,你们好。我在使用workqueue的过程中遇到一个问题。rn项目采用uClinux系统,VoIP相关的。rn现有两个驱动,一个是负责数据传输的,还有一个是负责打电话的。这两个驱动里分别使用了一个workqueue。在数据传输量很大时,负责数据传输的workqueue非常耗费资源,CPU占用能达到60-70%。这时候,我打电话,也就是让负责打电话的workqueue工作,但是此时打电话的workqueue执行会出现延时(这个打电话的workqueue对时间很敏感),打电话就不正常了。没有数据传输或者数据量很小时,一切正常。rn我尝试着将打电话的代码全部放到中断程序里做(这样任何人都不能打断他,除非更高级别的中断),然而打电话调用的API会出现睡眠的情况,内核会崩溃(中断程序中不能睡眠)。rnrn我现在想知道workqueue有没有优先级的概念?有的话我可以把打电话的workqueue优先级设置为高。这样不管数据传输那边有多忙,电话总是能抢到CPU啊!rn我查了网上的资料,workqueue其实就是一个内核线程,既然是线程,应该有优先级的概念啊。由于我没有内核编程的经验,还请有经验的大侠给予指导!rnrn小弟先谢谢了!rnrn

  前言关于RabbitMQ基本应用代码体验,。一工作队列RabbitMQ工作队列的出现是因为简单队列生产者和消费者是...

  中断不能睡眠的原因:睡眠会导致进程的调度,使得从中断切换到别的进程执行。但是由于Linux内核的调度器是基于进程进行调度的,也就是说,调度的实体是基于task_struct的,而中断处理程序执行的时候...

  向内核注册中断处理函数需要用到request_irq()函数,其中有一个irq的中断资源的中断号,那么注册函数是怎么通过这个中断号寻找到正确的硬件中断源的呢?就是具体硬件跟这个中断号的具体映射机制是如何?好比说当我需要用到串口中断为我服务时,通过输入这个中断号,系统是怎么找到我要注册的中断处理函数就是在串口中断上用到,从而当串口产生中断的时候,系统能够找到合适的irq_action向量表合适的偏移量,再找到我的中断处理函数?rnrnrn如果需要看内核代码的话,请指明看的步骤,谢谢~!

  本文对中断系统进行了全面的分析与探讨,主要包括中断控制器、中断分类、中断亲和力、中断线程化与SMP中的中断迁徙等。首先对中断工作原理进行了简要分析,接着详细探讨了中断亲和力的实现原理,最后对中断线程化...

  中断:打算cpu正常流程中断程序:向内核申请注册中断实现用户中断处理函数在不需要该中断的时候卸载中断...

http://ando2.com/zhongduanjizhi/269.html
锟斤拷锟斤拷锟斤拷QQ微锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷微锟斤拷
关于我们|联系我们|版权声明|网站地图|
Copyright © 2002-2019 现金彩票 版权所有