关于softirq/tasklet/workqueue

1、softirq

      软中断支持SMP,同一个softirq可以在不同的CPU上同时运行,softirq必须是可重入软中断是在编译期间静态分配的,它不像tasklet那样能被动态的注册或去除。kernel/softirq.c中定义了一个包含32个softirq_action结构体的数组。每个被注册的软中断都占据该数组的一项。因此最多可能有32个软中断。2.6版本的内核中定义了六个软中断:HI_SOFTIRQ、TIMER_SOFTIRQ、NET_TX_SOFTIRQ、NET_RX_SOFTIRQ、SCSI_SOFTIRQ、TASKLET_SOFTIRQ。

      软中断的特性:
      1).一个软中断不会抢占另外一个软中断。
      2).唯一可以抢占软中断的是中断处理程序。
      3).其他软中断(包括相同类型的)可以在其他的处理其上同时执行。
      4).一个注册的软中断必须在被标记后才能执行。
       5).软中断不可以自己休眠(即调用可阻塞的函数或sleep等)。
      6).索引号小的软中断在索引号大的软中断之前执行。

2、tasklet

      引入tasklet,最主要的是考虑支持SMP,提高SMP多个cpu的利用率;两个相同的tasklet决不会同时执行tasklet可以理解为softirq的派生,所以它的调度时机和软中断一样。对于内核中需要延迟执行的多数任务都可以用tasklet来完成,由于同类tasklet本身已经进行了同步保护,所以使用tasklet比软中断要简单的多,而且效率也不错。tasklet把任务延迟到安全时间执行的一种方式,在中断期间运行,即使被调度多次,tasklet也只运行一次不过tasklet可以在SMP系统上和其他不同的tasklet并行运行。在SMP系统上,tasklet还被确保在第一个调度它的CPU上运行,因为这样可以提供更好的高速缓存行为,从而提高性能。

与一般的软中断不同,某一段tasklet代码在某个时刻只能在一个CPU上运行,但不同的tasklet代码在同一时刻可以在多个CPU上并发地执行。Kernel/softirq.c中用tasklet_trylock()宏试图对当前要执行的tasklet(由指针t所指向)进行加锁,如果加锁成功(当前没有任何其他CPU正在执行这个tasklet),则用原子读函数atomic_read()进一步判断count成员的值。如果count为0,说明这个tasklet是允许执行的。如果tasklet_trylock()宏加锁不成功,或者因为当前tasklet的count值非0而不允许执行时,我们必须将这个tasklet重新放回到当前CPU的tasklet队列中,以留待这个CPU下次服务软中断向量TASKLET_SOFTIRQ时再执行。

为此进行这样几步操作:

(1)先关 CPU中断,以保证下面操作的原子性。

(2)把这个tasklet重新放回到当前CPU的tasklet队列的首部;

(3)调用__cpu_raise_softirq()函数在当前CPU上再触发一次软中断请求TASKLET_SOFTIRQ;

(4)开中断。
软中断和tasklet都是运行在中断上下文中,它们与任一进程无关,没有支持的进程完成重新调度。所以软中断和tasklet不能睡眠、不能阻塞,它们的代码中不能含有导致睡眠的动作,如减少信号量、从用户空间拷贝数据或手工分配内存等。也正是由于它们运行在中断上下文中,所以它们在同一个CPU上的执行是串行的,这样就不利于实时多媒体任务的优先处理。

       tasklet的特性:.不允许两个两个相同类型的tasklet同时执行,即使在不同的处理器上。

3、work queue

      如果推后执行的任务需要睡眠,那么就选择工作队列。另外,如果需要用一个可以重新调度的实体来执行你的下半部处理,也应该使用工作队列。它是唯一能在进程上下文运行的下半部实现的机制,也只有它才可以睡眠。这意味着在需要获得大量的内存时、在需要获取信号量时,在需要执行阻塞式的I/O操作时,它都会非常有用。workqueue造成的开销最大,因为它要涉及到内核线程甚至是上下文切换。这并不是说workqueue的低效,但每秒钟有数千次中断,就像网络子系统时常经历的那样,那么采用其他的机制可能更合适一些。尽管如此,针对大部分情况工作队列都能提供足够的支持。

      工作队列特性:
     1).工作队列会在进程上下文中执行!
     2).可以阻塞。(前两种机制是不可以阻塞的)
      3).可以被重新调度。(前两种只可以被中断处理程序打断)
     4).使用工作队列的两种形式:
            1>缺省工作者线程(works threads)
            2>自建的工作者线程
     5).在工作队列和内核其他部分之间使用锁机制就像在其他的进程上下文一样。
     6).默认允许响应中断。
     7).默认不持有任何锁。

4、softirq和tasklet共同点

       软中断和tasklet都是运行在中断上下文中,它们与任一进程无关,没有支持的进程完成重新调度。所以软中断和tasklet不能睡眠、不能阻塞,它们的代码中不能含有导致睡眠的动作,如减少信号量、从用户空间拷贝数据或手工分配内存等。也正是由于它们运行在中断上下文中,所以它们在同一个CPU上的执行是串行的,这样就不利于实时多媒体任务的优先处理。



            简单地说,一般的驱动程序的编写者需要做两个选择。首先,你是不是需要一个可调度的实体来执行需要推后完成的工作――从根本上来说,有休眠的需要吗?要是有,工作队列就是你的惟一选择。否则最好用tasklet。要是必须专注于性能的提高,那么就考虑softirq。 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值