Linux操作系统--中断、中断处理、中断上下部

注:本文资料全部来源于网络或书籍,同时加上个人理解。若有侵权,告知即删。若有错误,留言商讨。

中断响应过程:

中断请求——>CPU响应中断,清除中断标志——>保护现场——>确定中断号,响应中断服务程序——>中断返回、恢复现场

 

1、中断上半部:禁止响应其他中断执行,下半部:打开中断执行

2、如果设备使用中断,相应的驱动程序就会注册一个中断处理程序。

注册中断处理程序:request_irp():分配一条给定的中断线。

中断和重入:通常所有的中断处理程序是无须重入的。中断响应期间,相同中断的中断线在所有处理器上被屏蔽,但是其它中断线都是打开的。可以实现中断嵌套。

3、共享的中断处理程序(注册标志:IRQF_SHARED):中断处理程序可以共享中断线,内核接受到一个中断的时候会依次调用在该中断线上注册的所有程序。因此中断处理程序必须知道它是否应该为这个中断响应负责。如果没有产生与驱动程序相关的中断,该处理程序立即退出。

4、进程上下文【内核代表进程执行(执行系统调用或者执行内核线程)】可以睡眠,可以发生进程调度,中断上下文不能睡眠。

5、控制中断系统

通过禁止中断,可以确保某个中断处理程序不会抢占当前的代码,禁止中断可以禁止内核抢占,不管是禁止中断还是禁止内核抢占,都没有提供机制来防护来自其他处理器的并发访问。Linux内核支持多处理器,因此内核代码需要获取某种锁来防止其他处理器对数据的并发访问。获取这些锁的同时伴随着禁止本地中断锁提供保护机制,防止其他处理器并发访问

 

上半部需要处理的事情:对时间敏感、和硬件相关、要求保证不被中断的程序需要放在中断处理程序中。其他所有任务放在下半部。(上半部只能通过中断处理程序实现)

 

6、下半部和退后执行的工作:通常下半部在中断处理程序返回之后立马就会运行,下半部执行的关键在于当他们运行的时候允许响应中断。

7、下半部的实现机制:

       (1) bottom half (BH):现在不使用;(2)任务队列(性能瓶颈,被工作队列替代)

 

(3)软中断:是一组静态定义的下半部接口,有32个,可以在所有处理器上同时执行,即使两个类型相同也可以,要求可重入。(性能好,少用)【2.6.34内核已经使用9个】【中断上下文

       1:一个软中断不会抢占另一个软中断,软中断只能被中断程序打断,可以响应中断,但是不能休眠。

       2:静态注册软中断,和内核一起编译——>触发软中断,中断处理程序返回之前会触发软中断,以便在稍后执行

       3:软中断响应执行时机:硬件中断代码返回处、ksoftirq内核线程(每个处理器有一个)中、显示的检查和执行软中断的代码中

       4:软中断保留给系统中对时间要求最严格的的以及最重要的下半部使用。

       5:如果同一个软中断被触发,另外一个处理器可以同时运行其处理程序,这意味着任何共享数据都需要严格保护。

//软中断注册函数
open_softirq(int index, void (*action)(struct softirq_action *));
//软中断触发
raise_softirq(int index);

所有的软中断被存放在一个静态数组中,数组的每一个元素都是一个软中断,数组下表就是优先级。

static struct softirq_action softirq_vec[NR_SOFTIRQS];

软中断的过程,与硬件中断唯一不同 的地方是从中断标记到中断服务程序的映射过程。在CPU的硬件中断发生之后,CPU需要将硬件中断请求通过向量表映射成具体的服务程序,这个过程是硬件自 动完成的,但是软中断不是,其需要守护线程去实现这一过程,这也就是软件模拟的中断,故称之为软中断。

 

(4)tasklet:基于软中断实现的灵活性强的动态创建的下半部实现机制,不同类型可以在不同处理器同时执行,相同类型不能同时执行(不需要设计为可重入)。(易用,性能较好,满足普通需求)【中断上下文

被激活的tasklet:包需要调度的tasklet存放在每个处理器都有两个tasklet链表中,tasklet_vec 和tasklet_hi_vec,链表的每个元素就是 struct tasklet_struct。【激活函数 tasklet_schedule() 】

do_softirq() 函数会下一个时机调度,并执行上述激活的函数。

所有的tasklet都通过重复调用 HI_SOFTIRQ和TASKLET_SOFTIRQ这两个软中断实现。

 引入tasklet,最主要的是考虑支持SMP,提高SMP多个cpu的利用率;两个相同的tasklet决不会同时执行。tasklet可以理解为softirq的派生,所以它的调度时机和软中断一样。对于内核中需要延迟执行的多数任务都可以用tasklet来完成,由于同类tasklet本身已经进行了同步保护,所以使用tasklet比软中断要简单的多,而且效率也不错。tasklet把任务延迟到安全时间执行的一种方式,在中断期间运行,即使被调度多次,tasklet也只运行一次,不过tasklet可以在SMP系统上和其他不同的tasklet并行运行。在SMP系统上,tasklet还被确保在第一个调度它的CPU上运行,因为这样可以提供更好的高速缓存行为,从而提高性能。

 

ksoftirq线程:当内核出现大量的软中断和tasklet时,这些内核线程辅助处理。

引入该内核线程的原因:方案1:只要还有已经触发并等待处理的软中断,本次执行应当负责执行,当软中断重复自己触发软中断,会一直执行软中断,会导致用户进程饥饿。方案2:本次执行不负责新触发的中断,被安排到下一次的do_softirq()中,但是也会导致新触发的软中断不能马上处理。

折中:不会立即处理新触发的软中断,同时,在出现大量的软中断的时候,激活一组内核线程来处理这些负载。这些内核线程运行在最低优先级上。

 

(5)工作队列:可以把内核任务推后,交给一个内核线程处理。【进程上下文

        如果推后执行的任务需要睡眠,那么就选择工作队列。另外,如果需要用一个可以重新调度的实体来执行你的下半部处理,也应该使用工作队列。它是唯一能在进程上下文运行的下半部实现的机制,也只有它才可以睡眠。这意味着在需要获得大量的内存时、在需要获取信号量时,在需要执行阻塞式的I/O操作时,它都会非常有用。work queue造成的开销最大,因为它要涉及到内核线程甚至是上下文切换。这并不是说work queue的低效,但每秒钟有数千次中断,就像网络子系统时常经历的那样,那么采用其他的机制可能更合适一些。 尽管如此,针对大部分情况工作队列都能提供足够的支持。如果推后执行的任务需要睡眠,那么就选择工作队列。如果推后执行的任务不需要睡眠,那么就选择tasklet。

      工作队列子系统提供了一个or组缺省的内核线程来处理推后执行的工作。驱动程序也可以创建一个专用的工作者内核线程。不过一般不建议。

系统存在多种工作者线程,每种工作者线程在每个处理器上有一个工作者线程,每个工作者线程有一个工作队列。

默认内核只有event这一种类型的工作者线程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值