Linux2.4.x内核软中断机制[2]

[入库:2005年9月19日] [更新:2007年3月24日]

本文简介:

  tasklet_schedule(&my_tasklet); /*
  登记my_tasklet,允许系统在适当的时候进行调度运行,相当于queue_task(&my_task,&tq_immediate)和mark_bh(IMMEDIATE_BH) */
  可见tasklet的使用比task queue更简单,而且,tasklet还能更好的支持SMP结构,因此,在新的2.4.x内核中,tasklet是建议的异步任务执行机制。除了以上提到的使用步骤外,tasklet机制还提供了另外一些调用接口:
  
  DECLARE_TASKLET_DISABLED(name,function,data); /*
  和DECLARE_TASKLET()类似,不过即使被调度到也不会马上运行,必须等到enable */
  tasklet_enable(struct tasklet_struct *); /* tasklet使能 */
  tasklet_disble(struct tasklet_struct *); /* 禁用tasklet,只要tasklet还没运行,则会推迟到它被enable */
  tasklet_init(struct tasklet_struct *,void (*func)(unsigned long),unsigned long); /* 类似DECLARE_TASKLET() */
  tasklet_kill(struct tasklet_struct *); /* 清除指定tasklet的可调度位,即不允许调度该tasklet,但不做tasklet本身的清除 */
  
  前面提到过,在2.4.x内核中,bottom half是利用tasklet机制实现的,它表现在所有的bottom half动作都以一类tasklet的形式运行,这类tasklet与我们一般使用的tasklet不同。
  
  在2.4.x中,系统定义了两个tasklet队列的向量表,每个向量对应一个CPU(向量表大小为系统能支持的CPU最大个数,SMP方式下目前2.4.2为32)组织成一个tasklet链表:
  
  struct tasklet_head tasklet_vec[NR_CPUS] __cacheline_aligned;
  struct tasklet_head tasklet_hi_vec[NR_CPUS] __cacheline_aligned;
  
  另外,对于32个bottom half,系统也定义了对应的32个tasklet结构:
  
  struct tasklet_struct bh_task_vec[32];
  在软中断子系统初始化时,这组tasklet的动作被初始化为bh_action(nr),而bh_action(nr)就会去调用bh_base[nr]的函数指针,从而与bottom half的语义挂钩。mark_bh(nr)被实现为调用tasklet_hi_schedule(bh_tasklet_vec+nr),在这个函数中,bh_tasklet_vec[nr]将被挂接在tasklet_hi_vec[cpu]链上(其中cpu为当前cpu编号,也就是说哪个cpu提出了bottom half的请求,则在哪个cpu上执行该请求),然后激发HI_SOFTIRQ软中断信号,从而在HI_SOFTIRQ的中断响应中启动运行。
  
  tasklet_schedule(&my_tasklet)将把my_tasklet挂接到tasklet_vec[cpu]上,激发TASKLET_SOFTIRQ,在TASKLET_SOFTIRQ的中断响应中执行。HI_SOFTIRQ和TASKLET_SOFTIRQ是softirq子系统中的术语,下一节将对它做介绍。
  
  五. softirq
  
  从前面的讨论可以看出,task queue基于bottom half,bottom half基于tasklet,而tasklet则基于softirq。
  
  可以这么说,softirq沿用的是最早的bottom half思想,但在这个"bottom half"机制之上,已经实现了一个更加庞大和复杂的软中断子系统
  
  struct softirq_action
  {
   void (*action)(struct softirq_action *);
   void *data;
  };
  static struct softirq_action softirq_vec[32] __cacheline_aligned;
  这个softirq_vec[]仅比bh_base[]增加了action()函数的参数,在执行上,softirq比bottom half的限制更少。
  
  和bottom half类似,系统也预定义了几个softirq_vec[]结构的用途,通过以下枚举表示:
  
  enum
  {
   HI_SOFTIRQ=0,
   NET_TX_SOFTIRQ,
   NET_RX_SOFTIRQ,
   TASKLET_SOFTIRQ
  };
  HI_SOFTIRQ被用于实现bottom half,TASKLET_SOFTIRQ用于公共的tasklet使用,NET_TX_SOFTIRQ和NET_RX_SOFTIRQ用于网络系统的报文收发。在软中断子系统初始化(softirq_init())时,调用了open_softirq()对HI_SOFTIRQ和TASKLET_SOFTIRQ做了初始化:
  
  void open_softirq(int nr, void (*action)(struct softirq_action*), void *data)
  
  open_softirq()会填充softirq_vec[nr],将action和data设为传入的参数。TASKLET_SOFTIRQ填充为tasklet_action(NULL),HI_SOFTIRQ填充为tasklet_hi_action(NULL),在do_softirq()函数中,这两个函数会被调用,分别启动tasklet_vec[cpu]和tasklet_hi_vec[cpu]链上的tasklet运行。
  
  static inline void __cpu_raise_softirq(int cpu, int nr)
  
  这个函数用来激活软中断,实际上就是第cpu号CPU的第nr号软中断的active位置1。在do_softirq()中将判断这个active位。tasklet_schedule()和tasklet_hi_schedule()都会调用这个函数。
  

本文关键:Linux2.4.x内核软中断机制
  相关方案
Google
 

本站最佳浏览方式为 分辨率 1024x768 IE 6.0(或更高版本的 IE浏览器)

go top