您的位置:首页 > 其它

内核中断下半部机制

2014-05-12 00:00 260 查看
下半部的主要任务就是执行中断相关的,不在中断处理器中执行的工作。如何将中断任务分为上下两部分分别执行呢,如下提供一些参考:

如果工作对时间敏感,那么在中断处理器中执行。

如果工作与硬件相关,在中断处理器中执行。

如果工作需要确保另一个中断不能打断它,在中断处理器中执行。

对于其他的情况,一般考虑在下半部中执行。

通常就尽量使中断处理程序快速完成,将一些不需要迅速处理的工作推迟到下半部中去执行。推迟是指现在暂时不执行,也不是在将来的某个特定时刻执行,而是在系统不是很忙的时候再执行。总的来说,上半部代码执行时一些或所有中断被禁用,而下半部代码在执行的时候所有的中断是打开的。
另一种推迟工作的机制是内核计时器,与下半部机制不同,计时器将工作推迟到某个指定的时间去执行。历史上和现在正在使用的下半部机制如下表所示:
BottomHalf Status
BH 在2.5中被移除
Taskqueues Softirq Tasklet
在2.5中被移除 2.3中开始出现
Workqueues 2.5中开始出现
微线程与软中断不同的地方是:微线程在同一时刻只能在一个处理器上运行。另外,不同的微线程可同时运行于不同的处理器上。
下半部之间的同步
微线程相对自己来说是串行的,即相同的微线程不会同时运行,即便是在不同的处理器上。所以无需考虑微线程之间的同步。
软中断没有提供串行化,所以所有共享的数据需要适当的锁定。
在进程上下文中,访问下半部共享数据,需要禁用下半部处理并在访问数据之前获得一个锁。
在中断上下文中,访问下半部共享数据,需要禁用中断并在访问数据之前获得一个锁。
任何在一个工作队列中的共享数据也需要锁定。
禁用下半部
通常情况下,仅仅禁用下半部是不够的,需要获得一个锁,并禁用下半部,特别是在驱动程序中。对于内核核心代码,只需要禁用下半部就行了。
禁用下半部的一些函数如下:
Method
Description
void local_bh_disable()
Disables softirq andtasklet processing on the local
processor
void local_bh_enable()
Enables softirq and taskletprocessing on the local
processor
这些调用可以被嵌套,当然它们调用的次数应该相同。即local_bh_disable()与local_bh_enable()函数之间的调用次数应该相同。这些函数通过preempt_count(内核抢占与用户相同的计数器)来维护每个任务的计数器。这些函数对每个支持的平台来说是唯一的,下面是一些相同代码:
/*
* disable local bottom halves by incrementing the preempt_count
*/
void local_bh_disable(void)
{
struct thread_info *t = current_thread_info();
t ->preempt_count += SOFTIRQ_OFFSET;
}
/*
* decrement the preempt_count - this will ‘automatically’ enable
* bottom halves if the count returns to zero
*
* optionally run any bottom halves that are pending
*/
void local_bh_enable(void)
{
struct thread_info *t = current_thread_info();
t->preempt_count -= SOFTIRQ_OFFSET;
/*
* is preempt_count zero and are any bottom halves pending?
* if so, run them
*/
if (unlikely(!t->preempt_count && softirq_pending(smp_processor_id())))
do_softirq();
}


这些函数只对软中断和微线程有意义。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息