linux 内核抢占
什么是内核抢占呢?
周期性时钟中断:对于用户任务,当每个时钟中断到来后都会检查它的实际运行时间是否超过理想运行时间,或者运行队列中有没有优先级更高的进程,一般如果满足其中一个条件就会设置重新调度标志,然后在中断返回用户态的前夕发生调度,这是所谓的用户任务抢占。但是如果处于一个内核态的任务正在运行,这个时候发生中断唤醒了一个高优先级的任务,那么这个被唤醒的任务能否被调度执行呢?这个时候就会分两种情况分析,如果是抢占式内核那么高优先级任务就有可能抢占当前任务而调度执行(之所有是有可能是因为两者虚拟运行时间差值要大于抢占粒度才允许抢占),如果是不可抢占式内核那么不允许抢占,除非当前进程执行完或者主动发生调度高优先级进程该有机会被调度。也就是说,支持内核抢占的内核不仅允许在用户态的任务可以被抢占,处在内核态的任务也允许被抢占(请注意这里说的是内核态,因为用户空间任务可以通过系统调用等进入内核态),这样对于交互性或者低延迟的应用场景很友好,如手持设备和桌面应用,响应会很快。而对于服务器来说,它就对吞吐量要求较高,希望获得更多的cpu时间,而交互性或者低延迟都是次要的,所以被设计成不可抢占式内核。
下图给出非抢占式内核调度情况:
下图给出抢占式内核调度情况:
对比两个图可以发现:采用抢占式内核调度的情况下,在中断中唤醒一个高优先级任务能够得到很好的响应。
关于抢占式内核还是不可抢占式内核的选择在源码的kernel/Kconfig.preempt有所描述:
choice prompt "Preemption Model" default PREEMPT_NONE config PREEMPT_NONE bool "No Forced Preemption (Server)"... config PREEMPT_VOLUNTARY bool "Voluntary Kernel Preemption (Desktop)"... config PREEMPT bool "Preemptible Kernel (Low-Latency Desktop)"... config PREEMPT_RT bool "Fully Preemptible Kernel (Real-Time)" depends on EXPERT && ARCH_SUPPORTS_RT ... endchoice