Chinaunix首页 | 论坛 | 博客
  • 博客访问: 191099
  • 博文数量: 76
  • 博客积分: 2510
  • 博客等级: 少校
  • 技术积分: 831
  • 用 户 组: 普通用户
  • 注册时间: 2007-12-31 00:52
文章分类

全部博文(76)

文章存档

2010年(58)

2009年(18)

我的朋友

分类:

2010-03-29 13:48:33


Softirqs

在编译期间静态分配,一般采用tasklet会更好,Softirq适用于对于时间要求严格并能自己高效地完成加锁工作的应用。


目前只有网络和SCSI两个子系统直接使用软中断,内核定时器和tasklet都是基于softirq实现的。


softirq 的类型
enum
{
    HI_SOFTIRQ=0,
    TIMER_SOFTIRQ,
    NET_TX_SOFTIRQ,
    NET_RX_SOFTIRQ,
    BLOCK_SOFTIRQ,
    TASKLET_SOFTIRQ,
    SCHED_SOFTIRQ,
#ifdef CONFIG_HIGH_RES_TIMERS
    HRTIMER_SOFTIRQ,
#endif
    RCU_SOFTIRQ,     /* Preferable RCU should always be the last softirq */
};



注册softirq
void open_softirq(int nr, void (*action)(struct softirq_action *))


如:
    open_softirq(NET_TX_SOFTIRQ, net_tx_action);
    open_softirq(NET_RX_SOFTIRQ, net_rx_action);



执行softirq
asmlinkage void do_softirq(void)


触发softirq
void raise_softirq(unsigned int nr)

此函数可将一个软中断设置为挂起状态,并让它在下次do_softirq()被调用时投入运行,使用该函数之前须先禁止中断。
常见的softirq触发一般在ISR中进行,ISR执行完硬件设备的相关操作后,然后触发相应的软中断,最后退出ISR,接着内核在执行完ISR退出以后,马上调用do_softirq函数,让sotfirq完成ISR剩下的工作。


softirq的处理程序如
net_tx_action在执行时,本地的硬件中断是激活的,而本地软中断是被禁止的, 但它自己不能休眠。

相同类型和不同类型的软中断可以在其它处理器上同时执行,这表明任何共享数据,包括软中断处理程序内部使用的全局变量,都需要严格的锁保护。




-------------------------------------------------------------------------------------------------------------------------
Tasklets

基于softirq实现的,分别为 HI_SOFTIRQ TASKLET_SOFTIRQ 两种
HI_SOFTIRQ 先于 TASKLET_SOFTIRQ 运行。


Tasklets有两种状态定义:
    TASKLET_STATE_SCHED,    /* Tasklet is scheduled for execution */
    TASKLET_STATE_RUN    /* Tasklet is running (SMP only) */




创建
Tasklets
静态方式:
DECLARE_TASKLET(name, func, data)
DECLARE_TASKLET_DISABLED(name, func, data)

动态方式:
tasklet_init(struct tasklet_struct *t,
             void (*func)(unsigned long), unsigned long data);



调度、执行tasklet:
HI_SOFTIRQ 类型:
static inline void tasklet_hi_schedule(struct tasklet_struct *t)
  -->
唤醒Softirq
 
static void tasklet_hi_action(struct softirq_action *a)
  --> 执行softirq

TASKLET_SOFTIRQ 类型:
static inline void tasklet_schedule(struct tasklet_struct *t)
 -->
唤醒Softirq

static void tasklet_action(struct softirq_action *a)
  --> 执行softirq



使能、禁止和杀死tasklet
static inline void tasklet_enable(struct tasklet_struct *t)

static inline void tasklet_disable(struct tasklet_struct *t)

static inline void tasklet_disable_nosync(struct tasklet_struct *t)

void tasklet_kill(struct tasklet_struct *t);

void tasklet_kill_immediate(struct tasklet_struct *t, unsigned int cpu);




同一时间里,相同类型的tasklet只能有一个执行,即使在SMP下,相同的tasklet不能同时在不同的CPU上执行,但不同的的tasklet则可以在不同的CPU上同时执行。因此,如果tasklet和其他tasklet或者softirq共享了数据,则必须采取适当的锁保护。

tasklet不能睡眠,因此不能在其中使用信号量或者阻塞式的函数。

tasklet运行时允许响应中断,因此如果tasklet和ISR之间共享数据时,需要采取关中断,获取锁等措施。

在tasklet被调度以后,只要有机会,它就会尽可能早地运行。在没有运行之前,如果有一个相同的tasklet被调度了,那么它仍然只运行一次;如果此时它已经在另一个CPU开始运行了,那么这个新的tasklet会被重新调度并再次运行。







阅读(738) | 评论(0) | 转发(0) |
0

上一篇:Linux并行与竞争

下一篇:Linux 时间管理

给主人留下些什么吧!~~