linux kenrel现在支持内核抢占的,这样是为了保证kernel良好的实时性。 当一个进程处于核心态的时候,也是可以被其他进程抢占。这个在kernel中: CONFIG_PREEMPT
抢占时机可以发生在:
1. 内核preempt_schedule 调用的时候,(像每次preempt_enable时候会掉哟给你preempt_check_resched检查(test_thread_flag(TIF_NEED_RESCHED)))。内核关键数据结构中spin_unlock中都会调用preempt_enable的。
2. 处理器硬件中断请求之后(TICK中断也是?),如果返回核心态,特定于体系结构的汇编例程会检查抢占计数器(preempt_count)是否为0,以及是否设置了重调度标志(test_thread_flag(TIF_NEED_RESCHED)), 如果都满足,调用preempt_schedule_irq ,调用时停用中断,防止造成递归调用。
如果内核停用了当前CPU中断,是不能抢占的(irqs_disabled()),这个会在prreempt_schedule中判断。
我们通过preempt_disable 调用将preempt_count加1来停用抢占。 某些时候需要停用抢占来保护内核临界区,需要停用内核抢占。像SMP系统中,用于保护多核竞争的spin_lock中会调用preempt_disable先停用抢占的。