Linux内核中断处理“下半部”机制(超详细~)

Linux内核中断处理“下半部”机制(超详细~)

baf13a57f43c3110a2561de4723952fe.png

a7bfc07dec92bf02c15b9314e9793e5a.png

///插播一条:我自己在今年年初录制了一套还比较系统的入门单片机教程,想要的同学找我拿就行了免費的,私信我就可以哦~点我头像黑色字体加我地球呺也能领取哦。最近比较闲,带做毕设,带学生参加省级或以上比赛///

1a796c77ed6a5cb1797be9198acb7b4d.png

1.中断处理“下半部”机制

·中断服务程序一般都是在中断请求关闭的条件下执行的,以避免嵌套而使中断控制复杂化。但是,中断是一个随机事件,它随时会到来,如果关中断的时间太长,CPU就不能及时响应其他的中断请求,从而造成中断的丢失。

·因此,Linux内核的目标就是尽可能快的处理完中断请求,尽其所能把更多的处理向后推迟。例如,假设一个数据块已经达到了网线,当中断控制器接受到这个中断请求信号时,Linux内核只是简单地标志数据到来了,然后让处理器恢复到它以前运行的状态,其余的处理稍后再进行(如把数据移入一个缓冲区,接受数据的进程就可以在缓冲区找到数据)。

·因此,内核把中断处理分为两部分:上半部(top-half)和下半部(bottom-half),上半部(就是中断服务程序)内核立即执行,而下半部(就是一些内核函数)留着稍后处理。

·首先:一个快速的“上半部”来处理硬件发出的请求,它必须在一个新的中断产生之前终止。通常,除了在设备和一些内存缓冲区(如果你的设备用到了DMA,就不止这些)之间移动或传送数据,确定硬件是否处于健全的状态之外,这一部分做的工作很少。

·第二:“下半部”运行时是允许中断请求的,而上半部运行时是关中断的,这是二者之间的主要区别。

·内核到底什么时候执行下半部,以何种方式组织下半部?

·这就是我们要讨论的下半部实现机制,这种机制在内核的演变过程中不断得到改进,在以前的内核中,这个机制叫做bottom-half(以下简称BH)。但是,Linux的这种bottom-half机制有两个缺点:

.在任意一时刻,系统只能有一个CPU可以执行BH代码,以防止两个或多个CPU同时来执行BH函数而相互干扰。因此BH代码的执行是严格“串行化”的。

.BH函数不允许嵌套。

·这两个缺点在单CPU系统中是无关紧要的,但在SMP系统中却是非常致命的。因为BH机制的严格串行化执行显然没有充分利用SMP系统的多CPU特点。为此,在2.4以后的版本中有了新的发展和改进,改进的目标使下半部可以在多处理机上并行执行,并有助于驱动程序的开发者进行驱动程序的开发。下面主要介绍3种2.6内核中的“下半部”处理机制:

.软中断请求(softirq)机制

.小任务(tasklet)机制

.工作队列机制

·以上三种机制的比较如下图所示:

c2f203fad533ac0873568557fd5750df.png

2.软中断请求(softirq)机制

·Linux的softirq机制是与SMP紧密不可分的。为此,整个softirq机制的设计与实现中自始自终都贯彻了一个思想:“谁触发,谁执行”(Who marks,Who runs),也即触发软中断的那个CPU负责执行它所触发的软中断,而且每个CPU都有它自己的软中断触发与控制机制。这个设计思想也使得softirq机制充分利用了SMP系统的性能和特点。

2.1软中断描述符

·Linux在include/linux/interrupt.h头文件中定义了数据结构softirq_action,来描述一个软中断请求,如下所示:

/* PLEASE, avoid to allocate new softirqs, if you need not _really_ high

   frequency threaded job scheduling. For almost all the purposes

   tasklets are more than enough. F.e. all serial device BHs et

   al. should be converted to tasklets, not to softirqs.

 */

enum

{

HI_SOFTIRQ=0, //用于实现高优先级的软中断

TIMER_SOFTIRQ,

NET_TX_SOFTIRQ, //用于网络数据的发送

NET_RX_SOFTIRQ, //用于网络数据的接收

BLOCK_SOFTIRQ,

BLOCK_IOPOLL_SOFTIRQ,

TASKLET_SOFTIRQ, //用于实现tasklet软中断

SCHED_SOFTIRQ,

HRTIMER_SOFTIRQ,

RCU_SOFTIRQ, /* Preferable RCU should always be the last softirq */

NR_SOFTIRQS

};

/* map softirq index to softirq name. update 'softirq_to_name' in

 * kernel/softirq.c when adding a new softirq.

 */

extern char *softirq_to_name[NR_SOFTIRQS];

/* softirq mask and active fields moved to irq_cpustat_t in

 * asm/hardirq.h to get better cache usage. KAO

 */

struct softirq_action

{

void(*action)(struct softirq_action *);

};

asmlinkage void do_softirq(void);

asmlinkage void __do_softirq(void);

·其中,函数指针action指向软中断请求的服务函数。基于上述软中断描述符,Linux在kernel/softirq.c文件中定义了一个全局的softirq_vec数组:

·static struct softirq_action softirq_vec[NR_SOFTIRQS] __cacheline_aligned_in_smp;

·在这里系统一共定义了10个软中断请求描述符。软中断向量i(0≤i≤9)所对应的软中断请求描述符就是softirq_vec[i]。这个数组是个系统全局数组,即它被所有的CPU所共享。这里需要注意的一点是:每个CPU虽然都有它自己的触发和控制机制,并且只执行他自己所触发的软中断请求,但是各个CPU所执行的软中断服务例程却是相同的,也即都是执行softirq_vec[ ]数组中定义的软中断服务函数。Linux在kernel/softirq.c中的相关代码如下:

/*

   - No shared variables, all the data are CPU local.

   - If a softirq needs serialization, let it serialize itself

     by its own spinlocks.

   - Even if softirq is serialized, only local cpu is marked for

     execution. Hence, we get something sort of weak cpu binding.

     Though it is still not clear, will it result in better locality

     or will not.

   Examples:

   - NET RX softirq. It is multithreaded and does not require

     any global serialization.

   - NET TX softirq. It kicks software netdevice queues, hence

     it is logically serialized per device, but this serialization

     is invisible to common code.

   - Tasklets: serialized wrt itself.

 */

#ifndef __ARCH_IRQ_STAT

irq_cpustat_t irq_stat[NR_CPUS] ____cacheline_aligned;

EXPORT_SYMBOL(irq_stat);

#endif

static struct softirq_action softirq_vec[NR_SOFTIRQS] __cacheline_aligned_in_smp;

DEFINE_PER_CPU(struct task_struct *, ksoftirqd);

char *softirq_to_name[NR_SOFTIRQS] = {

"HI", "TIMER", "NET_TX", "NET_RX", "BLOCK", "BLOC

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值