将中断转换成线程
当前的linux内核(2.6.22,)有数种方法可用于处理设备的工作。当一个设备执行了一个需要CPU采取行动的
异步事件 并且启用了中断功能,该设备发送一个用于抢占CPU的中断信号,无论CPU正在做什么,它都会
替发送中断信号的设备执行中断服务程序(Interrrupt Service Routine,简称ISR)。ISR执行时的优先级高于
任何用户任务,而且会在CPU之上停用中断功能,或者(最低限度)是遮蔽当前的中断线。所以,只有另一个
中断能够抢占一个ISR,但只有在该ISR有重新启动中断功能时。
一个写的好的设备驱动程序会在ISR上执行尽可能少的工作,并将其他工作放到一个内核线程、一个tasklet
或者一个softirq。这些是linux为设备所提供的其他方法,用于进行异步事件所需要完成的工作,例如设备的
活动。
softirq是一个服务程序,它的执行时机为:从一个ISR返回之后以及继续执行被中断的进程之前。如果有太多
的softirq被排入队列,内核会唤醒一个具有高优先级的内核线程(ksoftirqd)以便完成它们。发展内核的过程
中对如何才算“有太多softirq”曾发生争论。ksoftirqd线程被启动的时机为:当有一个停用中断功能的softirq
被启动的时候,或是如果一个softirq进程,返回被抢占的进程之前,被处理的次数不止一次。
(这段话没怎么看懂)
tasklet如果softirq,它的执行时机也是在ISR之后以及继续执行被中断进程之前。tasklet跟softirq的差别在
于,同一个softirq可以同时在两个不同CPU上执行,而tasklet不能。因此,softirq必须可重入-使用上锁机制
防止任何全局变量或其他临界资源的并行存取,而tasklet不必这么做;换言之,tasklet不需要可重入。
tasklet跟softirq的另一个差别在于,执行tasklet函数的CPU可以不是引发tasklet的CPU。tasklet事实上是
由softirq实现而成的(咋实现的?)。实现tasklet的softirq函数只须确保不会有两个tasklet函数同时执行即可。
这也意味着tasklet可以被ksoftirqd线程所执行。
内核线程(kernel thread)是一种只能在内核之内运行的线程,它可以被ISR唤醒,来处理中断服务例程尚未
完成的任何工作,这样ISR可以很快返回,让被抢占的任何进程或内核活动得以继续下去。内核线程的行为
就像linux中的其他线程。它可以被调度,它的线程可以被修改,可以运行在特定CPU上,而且就像系统中的
任何其他线程那样可以被系统管理员控制/操控。
在此情况下,ISR通常会利用工作队列。工作队列是一种内核机制,就像其名称所指的那样,在队列中排队的
工作将会运行在一个worker kernel thread(负责处理任务的内核线程)中。有一个通用的worker kernel
thread称为keventd,如果内核并未配置一个特定的工作队列,它会被内核用于执行工作函数。对任何一个
被排入队列的工作而言,需要等排在它之前的所有工作函数都被处理之后,通用的keventd线程才会处理它,
因为队列处理工作的方式是按照FIFO的顺序。
内核线程的开销比softirq或tasklet稍微多一点,不过它更为灵活。在non-RT Linux内核下,softirq和tasklet
无法被具有任何优先级的任何进程抢占。相反的,softirq和tasklet可以抢占任何进程。所以,尽管内核线程
的开销比softirq和tasklet稍微多一点,但是它可以使得内核调度程序更为灵活,而且可以让系统管理员获得
更多的控制权(but 内核线程会忽略信号)。运行在实时环境的时候这种灵活性特别重要。
当一段程序被ISR,softirq或tasklet执行时,任何运行在CPU之上的进程将会被它抢占。它甚至会抢占正在为
其他设备进行的内核线程。Linux的这个行为有效的建立了一个策略:让ISR、softirq及tasklet在系统中成为
最高优先级的事件。
为了降低这些机制对系统所造成的时间等待,RT patch必须将他们全部都转换成内核线程,,,
阅读(2171) | 评论(0) | 转发(0) |