linux 软中断

转+原创

中断服务程序往往都是在CPU关中断的条件下执行的,以避免中断嵌套而使控制复杂
化。但是CPU关中断的时间不能太长,否则容易丢失中断信号。为此,Linux将中断服务
程序一分为二,各称作“Top Half”和“Bottom Half”。前者通常对时间要求较为严
格,必须在中断请求发生后立即或至少在一定的时间限制内完成。因此为了保证这种处
理能原子地完成,Top Half通常是在CPU关中断的条件下执行的。具体地说,Top Half的
范围包括:从在IDT中登记的中断入口函数一直到驱动程序注册在中断服务队列中的
ISR。而Bottom Half则是Top Half根据需要来调度执行的,这些操作允许延迟到稍后执
行,它的时间要求并不严格,因此它通常是在CPU开中断的条件下执行的。
但是,Linux的这种Bottom Half(以下简称BH)机制有两个缺点,也即:(1)在任
意一时刻,系统只能有一个CPU可以执行Bottom Half代码,以防止两个或多个CPU同时来
执行Bottom Half函数而相互干扰。因此BH代码的执行是严格“串行化”的。(2)BH函
数不允许嵌套。
这两个缺点在单CPU系统中是无关紧要的,但在SMP系统中却是非常致命的。因为BH机
制的严格串行化执行显然没有充分利用SMP系统的多CPU特点。为此,Linux2.4内核在BH
机制的基础上进行了扩展,这就是所谓的“软中断请求”(softirq)机制。

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


软中断是利用硬件中断的概念,用软件方式进行模拟,实现宏观上的异步执行效果。很多情况下,软中断和"信号"有些类似,同时,软中断又是和硬中断相对应的,"硬中断是外部设备对CPU的中断","软中断通常是硬中断服务程序对内核的中断","信号则是由内核(或其他进程)对某个进程的中断"(《Linux内核源代码情景分析》第三章)。
软中断的一种典型应用就是所谓的"下半部"(bottom half),它的得名来自于将硬件中断处理分离成"上半部"和"下半部"两个阶段的机制:上半部在屏蔽中断的上下文中运行,用于完成关键性的处理动作;而下半部则相对来说并不是非常紧急的,通常还是比较耗时的,因此由系统自行安排运行时机,不在中断服务上下文中执行。bottom half的应用也是激励内核发展出目前的软中断机制的原因。
软中断是linux系统原“底半处理”的升级,在原有的基础上发展的新的处理方式,以适应多cpu 、多线程的软中断处理。
软中断是实现系统API函数调用的手段
函数调用时将返回地址和CPU状态寄存器内容压栈,函数执行完毕后出栈返回断点继续执行。
软中断调用时将返回地址和CPU状态寄存器内容压栈,修改特权级,根据中断号查找中断向量表,找到ISR中断服务例程地址,跳转执行。
综上,函数调用和软中断调用的区别是,软中断多了修改特权级和查找中断向量表的功能,其他部分完全一样。
一般,系统程序由软件公司实现且不开源,你无法知道系统API函数的偏移地址,而且你写的应用程序和软件公司提供的系统程序是完全分开的,编译器无法将二者链接在一起,同时,系统程序需要核心态特权才能运行,此时用函数调用的办法是无法调用系统API函数的。解决这个问题的方法是使用软中断,当应用程序需要调用API时,就先设置功能号(如AX=0H),然后触发软中断(如INT 80H)。系统程序设置好中断向量表。这样,应用程序就可以间接找到系统API了。
有了软中断,就可以实现应用程序的动态加载。就像WINDOWS/Linux那样,应用程序和系统程序分别开发,不在一起编译连接,应用程序通过软中断调用系统提供的功能。

Linux软中断原理浅析
 
Linux中的软中断机制用于 系统中对时间要求最严格以及最重要的中断的下半部进行使用。( 中断分上下部,上部通常对时间要求严格)在系统设计过 程中,大家都清楚中断上下文不能处理太多的事情,需要快速的返回,否则很容易导致中断事件的丢失,所以这就产生了一个问题:中断发生之后的事务处理由谁来 完成?在前后台程序中,由于只有中断上下文和一个任务上下文,所以中断上下文触发事件,设置标记位,任务上下文循环扫描标记位,执行相应的动作,也就是中 断发生之后的事情由任务来完成了,只不过任务上下文采用扫描的方式,实时性不能得到保 证。在 Linux系统和Windows系统中,这个不断循环的任务就是本文所要讲述的软中断daemon。在Windows中处理耗时的中断事务称之为中 断延迟处理,在Linux中称之为中断下半部,显然中断上半部处理清中断之类十分清闲的动作,然后在退出中断服务程序时触发中断下半部,完成具体的功能。

硬中断是由外部事件引起的因此具有随机性和突发性;软中断是执行中断指令产生的,无面外部施加中断请求信号,因此中断的发生不是随机的而是由程序安排好的。
 
在Linux中,中断下半部的实现基于软中断机制。所以理清楚软中断机制的原理,那么中断下半部的实现也就非常简单了。通过上述的描述,大家也应该 清楚为什么要定义软中断机制了, 一句话就是为了要处理对时间要求苛刻的任务,恰好中断下半部就有这样的需求,所以其实现采用了软中断机制

  软中断是一种推后执行的机制,定时器,网卡的数据的处理是很典型的软中断,这个和中断向 量表里的中断是完全不一样的,以网络数据的处理为例,当网卡接到一个数据包后,其中断处理程序只是把数据复制到缓冲区,然后就告诉网卡,你可以再传数据给 我了,也就是中断返回,但在此之前,网卡的中断处理程序要置一个标志位,告诉操作系统有事要做,这个事就是软中断,但软中断只是很多中断返回时要做的事情 之一,操作系统每次中断返回时会检查着个标志位,看是否有事要做,如果有,就会去处理,象前面提到的网卡,这时候操作系统就回调用软中断的处理函数,网卡 的软中断程序就是做分析数据包啊,这个数据应该传给谁啊等这些工作.没有,就返回了,除了必须的部分
 
构成软中断机制的核心元素包括:
 
1、  软中断状态寄存器soft interrupt state(irq_stat)
2、  软中断向量表(softirq_vec)
3、  软中断守护daemon
  

软中断的工作工程模拟了实际的中断处理过程,当某一软中断时间发生后,首先需要设置对应的中断标记位,触发中断事务,然后唤醒守护线程去检测中断状 态寄存器,如果通过查询发现某一软中断事务发生之后,那么通过软中断向量表调用软中断服务程序action()。这就是软中断的过程,与硬件中断唯一不同 的地方是从中断标记到中断服务程序的映射过程。在CPU的硬件中断发生之后,CPU需要将硬件中断请求通过向量表映射成具体的服务程序,这个过程是硬件自 动完成的,但是软中断不是,其需要守护线程去实现这一过程,这也就是软件模拟的中断,故称之为软中断。


 
一个软中断不会去抢占另一个软中断,只有硬件中断才可以抢占软中断,所以软中断能够保证对时间的严格要求。
Linux中软中断实现分析
 
在Linux中最多可以注册32个软中断,目前系统用了6个软中断,他们为:定时器处理、SCSI处理、网络收发处理以及Tasklet机制,这里的tasklet机制就是用来实现下半部的,
 
描述软中断的核心数据结构为中断向量表,其定义如下:
struct softirq_action
 
{
 
void (*action)(struct softirq_action *); /* 软中断服务程序 */
 
void *data;                                         /* 服务程序输入参数 */
 
  
};
软中断守护daemon是软中断机制的实现核心,其实现过程也比较简单,通过查询软中断状态irq_stat来判断事件是否发生,如果发生,那么映 射到软中断向量表,调用执行注册的action函数就可以了。从这一点分析可以看出,软中断的服务程序的执行上下文为软中断daemon。在Linux中 软中断daemon线程函数为do_softirq()。
 
触发软中断事务通过raise_softirq()来实现,该函数就是在中断关闭的情况下设置软中断状态位,然后判断如果不在中断上下文,那么直接唤醒守护daemon。
 
常用的软中断函数列表如下:
1、  Open_softirq,注册一个软中断,将软中断服务程序注册到软中断向量表。2、  Raise_softirq,设置软中断状态bitmap,触发软中断事务。
 
Tasklet机制实现分析
Tasklet为一个软中断,考虑到优先级问题,分别占用了向量表中的0号和5号软中断。
 
当tasklet的软中断事件发生之后,执行tasklet-action的软中断服务程序,该服务程序会扫描一个tasklet的任务列表,执行该任务中的具体服务程序。在这里举一个例子加以说明:
 
当用户读写USB设备之后,发生了硬件中断,硬件中断服务程序会构建一个tasklet_struct,在该结构中指明了完成该中断任务的具体方法 函数(下半部执行函数),然后将tasklet_struct挂入tasklet的tasklet_struct链表中,这一步可以通过 tasklet_schedule函数完成。最后硬件中断服务程序退出并且CPU开始调度软中断daemon,软中断daemon会发现tasklet发 生了事件,其会执行tasklet-action,然后tasklet-action会扫描tasklet_struct链表,执行具体的USB中断服务 程序下半部。这就是应用tasklet完成中断下半部实现的整个过程。
  
Linux中的tasklet实现比较简单,其又封装了一个重要数据结构tasklet_struct,使用tasklet主要函数列表如下:
1、  tasklet_init,初始化一个tasklet_struct,当然可以采用静态初始化的方法,宏为:DECLARE_TASKLET。
 
2、  tasklet_schedule,调度一个tasklet,将输入的tasklet_struct添加到tasklet的链表中。
 
Linux中的软中断机制就是模拟了硬件中断的过程,其设计思想完全可以在其他嵌入式OS中得以应用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值