半部和推后执行的工作.ppt_第1页
半部和推后执行的工作.ppt_第2页
半部和推后执行的工作.ppt_第3页
半部和推后执行的工作.ppt_第4页
半部和推后执行的工作.ppt_第5页
已阅读5页,还剩18页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

7 下半部和推后执行的工作,1,8.1下半部,下半部(bottom half)的任务就是执行与中断处理密切相关但 中断处理程序本身不执行的工作。对于上半部和下半部之间 划分工作没有严格规则,但可遵循以下几点规则: 如果是一个任务对时间非常敏感,将其放在中断处理程序 中执行; 如果一个任务与硬件相关,将其放在中断处理程序中执行; 如果一个任务要保证不被其它中断打断,将其放在中断处 理程序中执行; 其他所有任务,考虑放置在下半部执行;,2,下半部的环境,内核提供三个不同形式的下半部实现机制: 软中断 tasklets 工作队列 其中,软中断使用的比较少,tasklets是下半部最常 用的方法,3,软中断,软中断是在编译期间静态分配的,它不像tasklet可以被动态地注册或注销。它定义在中: struct softirq_action void (*action)(sttruct softirq_action*); kernel/softirq.c中定义了一个包含有32个该结构体的数组 static struct softirq_action softirq_vecNR_SOFTIRQS; 每个被注册的软中断都占据该数组的一项,因此最多可能 有32个软中断。,4,1 软中断处理程序: 函数原型: void softirq_handler(struct softirq_action *) 一个软中断不会抢占另外一个软中断,实际上,唯一可以抢 占软中断的是中断处理程序。其它的软中断(甚至相同类型的 软中断)可以在其他处理器上同时执行。,5,2 执行软中断 一个注册的软中断必须在被标记后才会执行,这被称为触发 软中断。通常,中断处理程序会在返回前标记它的软中断, 使其在稍后被执行,于是,在合适的时刻,该软中断就会执 行: 从一个硬件中断代码处返回时 在ksoftirqd内核线程中 在那些显式检查和执行待处理的软中断的代码中,如网络子系统中,6,软中断保留给系统中对时间要求最严格以及最重要的下半部使用,目前,只有网络和SCSI子系统直接使用软中断,7,Tasklets,1 实现 Tasklets由HI_SOFTIRQ和TASKLET_SOFTIRQ两类中断代表 其中, HI_SOFTIRQ的优先级高于TASKLET_SOFTIRQ。 结构体(定义于) struct tasklet_struct struct tasklet_struct *next; /指向链表中的下一个结构体 unsigned long state; /tasklet的状态 atomic_t count; /引用计数器 void(*func)(unsigned long); /tasklet处理函数 unsigned long data; /给tasklet处理函数的参数 ,8,其中:state只能在0,TASKLET_STATE_SCHED(表明 tasklet已被调度)、TASKLET_STATE_RUN(表明tasklet 正在运行)间取值。 count是tasklet的引用计数器,如果不为0,则tasklet被禁 止,不允许执行;为0时,被激活,在被设置为挂起状态时, tasklet才能够执行。,9,调度tasklets: 已调度的tasklet存放在两个处理器数据结构:tasklet_vec(普通 tasklet)和tasklet_hi_vec(高优先级的tasklet)中。这两个数据结构 都是由tasklet_struct结构体构成的链表。链表中的每个tasklet_struct 代表一个不同的tasklet。 tasklets由tasklet_schedule()和tasklet_hi_schedule()函数进 行调度,它们接受一个指向tasklet_struct结构的指针做为参数。 两个函数非常类似(区别在于一个使用TASKLET_SOFTIRQD而 另一个用HI_SOFTIRQ)。,10,tasklet_schedule()执行步骤,检查tasklet的状态是否为TASKLET_STATE_SCHED。如果是,说明tasklet已经被调度过了,函数返回。 保存中断状态,然后禁止本地中断。在我们执行tasklet代码时,这么做能够保证处理器上的数据不会弄乱。 把需要调度的tasklet加到每个处理器的tasklet_vec链表或tasklet_hi_vec链表的表头上去。 唤起TASKLET_SOFTIRQ或HI_SOFTIRQ软中断,这样下一次调用do_softirq()时就会执行该tasklet。 恢复中断到原状态并返回。,11,使用Tasklets,1 声明自己的tasklet 创建tasklet分静态和动态两种,选择哪种方式取决于对 tasklet的直接引用或间接引用。 动态:将一个间接引用(一个指针)赋给一个动态创建的 tasklet_struct 结构的方式来初始化一个tasklet: tasklet_init(t,tasklet_handler,dev); 静态:使用中定义的两个宏中的一个: DELCARE_TASKLET(name,func,data); DECLARE_TASKLET_DISABLED(name,func,data);,12,实例:,DECLARE_TASKLET(my_tasklet,my_tasklet_han dler,dev);struct tasklet_struct my_tasklet=NULL,0,ATOMIC_INIT(0), tasklet_handler,dev; 创建一个名为my_tasklet,处理程序为tasklet_handler并且已 被激活的tasklet。当处理程序被调用的时候,dev就会被传递 给它,13,编写自己的tasklet处理程序,tasklet处理程序必须符合规定的函数类型: void tasklet_handler(unsigned long data) 因为是靠软中断实现,所以tasklet不能睡眠。这意味着你不能在 tasklet中使用信号量或者其他什么阻塞式的函数。由于tasklet运行 时允许响应中断,所以你必须做好预防工作,如果你的tasklet和 中断处理程序之间共享了某些数据的话,两个相同的tasklet决不 会同时执行,这点和软中断不同,尽管两个不同的tasklet可以在 两个处理器上同时执行。如果tasklet和其他tasklet或者是软件中断 共享了数据,必须进行适当地锁保护。,14,调度tasklet 通过调用tasklet_schedule()函数并传递给它相应的tasklet_struct 的指针,该tasklet就会被调度以便执行: tasklet_schedule(/*把my_tasklet标记为挂起*/ 调用tasklet_disable()函数禁止某个指定的tasklet,如果tasklet当前正 在执行,这个函数会等到它执行完毕再返回。 调用tasklet_disable_nosync()函数,也用来禁止指定的tasklet, 这个函数不会等到tasklet执行完毕。但这个函数不是很安全,因为 无法估计该tasklet是否仍在执行。,15,调用tasklet_enable()函数可以激活一个tasklet,如果希望激 活DECLARE_TASKLET_DISABLED()创建的tasklet,也可 以调用此函数。 tasklet_disable( /*tasklet现在被激活*/ 调用tasklet_kill()函数从挂起的队列中去掉一个tasklet,该函数的 参数是一个指向某个tasklet的tasklet_struct的长指针。在处理一个 经常重新调度它自身的tasklet的时候,从挂起的队列中移去已调 度的tasklet会很有用。这个函数首先等待该tasklet执行完毕,然后 再将它移去,该函数可能会引起休眠,所以禁止在中断上下文中 使用它。,16,ksoftirqd,问题:软中断被触发的频率可能会很高,处理函数有时还会 自行重复触发,也就是说,当一个软中断执行的时候,它可 以重新触发自己以便再次得到执行。如果软中断本身出现的 频率过高,再加上它们又有将自己重新设置为可执行状态的 能力,就会导致用户空间进程无法获得足够的处理器时间, 因而处于饥饿状态。而单纯对重新触发的软中断采取不立即 处理的策略也不是很理想的方案,这是一个亟待解决的问题,17,方案一:只要还有被触发并等待处理的软中断,本次执行就 会负责处理,重新触发的软中断也在本次执行返回前被处理。 这样可以保证对内核的软中断采取即时处理的方式。但当负 载很高的时候会出问题,用户空间被忽略了,这种方案只有系 统处于低负载的情况下,才会有理想的运行效果。,18,方案二:选择不处理重新触发的软中断。在从中断返回的时 候,内核和平常一样,也会检查所有挂起的软中断并处理它 们,但是,任何自行重新触发的软中断都不会马上处理,被 放到下一个软中断执行时机去处理。但在比较空闲的系统 中,这种方案就不是很好。尽管它能保证用户空间不处于饥 饿状态,但它却让软中断忍受饥饿的痛苦,根本没有好好利 用闲置的系统资源。,19,实际方案: 不立即处理重新触发的软中断。而作为改进,当大量软中断 出现的时候,内核会唤醒一组内核线程来处理这些负载。这 些线程在最低的优先级上运行,这能避免它们跟其他重要的 任务抢夺资源。但它们最终肯定会被执行, 所以,这个方案 能够保证在软中断负担很重的时候用户程序不会因为得不到 处理时间而处于饥饿状态。相应的,也能保证“过量”的软 中断终究会得到处理。最后,在空闲系统上,这个方案表现 良好,软中断处理得非常迅速(因为仅存的内核线程偿会马上 调度.),20,实现: 每个处理器都有一个线程,所有线程的名字为ksoftirad/n,区 别在于n,它对应的是处理器的编号。在一个双CPU的机器 上就有两个这样的线程,分别叫ksoftirad/0和ksoftirad/1。为 了保证只要有空闲的处理器,它们就会处理软中断,所以给 每个处理器都分配一个这样的线程。一旦线程被初始化,就 会执行死循环:,21,死循环: for(;) if(!softirq_pending(cpu) schedule(); set_current_satate(TASK_RUNNING); while(softirq_pending(cpu) do_softirq(); if(need_resched() schedule(); set_current_state(TASK_INTERRUPTILE); ,22,注释:只要有待处理的软中断(由softirq_pending(

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论