转: 内核抢占与preempt_count
时间:2010-12-29 来源:purple_river
本文转自: http://hi.baidu.com/yangyingchao/blog/item/af66b9d4e522940ca18bb705.html
简介:
暂时没有时间去系统的学习任务调度,这里仅仅给出关于内核抢占的相关数据结构和基 本原理。
1 相关数据结构
2 以下内容转自:内核抢占与其他大部分Unix变体和其他大部分的操作系统不同, Linux完整地支持内核抢占。 在不支持内核抢占的内核中,内核代码可以一直执行,到它完成为止。也就是说,调 度程序没有办法在一个内核级的任务正在执行的时候重新调度 – 内核中的各任务是 协作方式调度的,不具备抢占性。 在2.6版的内核中,内核引人了抢占能力;现在,只要重新调度是安全的,那么内核 就可以在任何时间抢占正在执行的任务。 那么,什么时候重新调度才是安全的呢?只要没有持有锁,内核就可以进行抢占。锁 是非抢占区域的标志。由于内核是支持SMP的,所以,如果没有持有锁,那么正在执 行的代码就是可重新导入的,也就是可以抢占的。 为了支持内核抢占所作的第一处变动就是每个进程的threadinfo引入了 preemptcount(threadinfo.preemptcount)计数器。该计数器初始值为0,每当使用锁的 时候数值加1,释放锁的时候数值减1。当数值为0的时候,内核就可执行抢占。从中断返回 内核空间的时候,内核会检查flag和preemptcount的值。如果flag中TIFNEEDRESCHED被 设置,并且preemptcount为0的话,这说明有一个更为重要的任务需要执行并且可以安全 地抢占,此时,调度程序就会调度(抢占当前进程)。如果preemptcount不为0,说明当前 任务持有锁,所以抢占是不安全的。这时,就会像通常那样直接从中断返回当前执行进程。 如果当前进程所持有的所有的锁都被释放了。那么preemptcount就会重新为0。此时,释 放锁的代码会检查needresched是否被设置。如果是的话,就会调用调度程序。有些内核 代码需要允许或禁止内核抢占。 如果内核中的进程被阻塞了,或它显式地调用了schedule(),内核抢占也会显式地发 生。这种形式的内核代码从来都是受支持的,因为根本无需额外的逻辑来保证内核可 以安全地发生被抢占。如果代码显式的调用了schedule(),那么它应该清楚自己是可 以安全地被抢占的。 内核抢占发生在:
注:
schedule()释放CPU控制权
权(不能被抢占) |