http://www.linuxforum.net/forum/showflat.php?Cat=&Board=linuxK&Number=693202&page=&view=&sb=&o=&vc=1
2.4.18和2.6.25.4-rt在任务调度上的不同
检查点:
A) 返回用户空间/返回内核空间:
—-2.4 :只在返回user space的时候才会检查任务是否需要被调度.
—-2.6:除了保留这个检查点,新增了返回内核空间的检查点, 这个检查点调用preempt_schedule_irq,这就是抢占式调度. 2.6中调用schedule前有个关键的操作, add_preempt_count(PREEMPT_ACTIVE),这标志这此schedule是抢占式调度,schedule 通过PREEMPT_ACTIVE这个标志知道这是一次抢占.
返回内核空间的时候只有peeempt_count==0才能够抢占当前进程. 2.6在返回用户空间的时候检查两个标志:TIF_NEED_RESCHED和新增的TIF_NEED_RESCHED_DELAYED, 而返回内核空间只检查TIF_NEED_RESCHED.
B)内核中的其他检查点
这些剩余的检查点分散在diver/mm和fs的一些地方, 这些检查点,能够提高内核的响应速度,这种加查点加速了对当前需要调度的进程的调度速度,而不是只有在返回user space/kernel space的时候才检查.
—-2.4: 比较单纯,就是检查current->need_resched (TASK_NEED_RESCHED),然后调用schedule.
—-2.6: 有两种检查点,TIF_NEED_RESCHED和新增的TIF_NEED_RESCHED_DELAYED.主要区别在A)中已有叙述.另一而主要区别是2.6中扩展了很多抢占式的检查点.
TIF_NEED_RESCHED:返回user space和返回kernel space都要检查.need_resched()也只检查这个标志. 而这个标记实现的检查点又有两种途径:
a)通过preempt_check_resched 实现的检查点,进行的是抢占式调度. 然后直接调用,和通过unlock spin,bh,rwlock这些函数(调用preempt_enable时)广泛分布到内核各个地方,会调用preempt_schedule.
b)通过need_resched()实现的检查点: 这个途径实现的检查点一部分是非抢占式调度,另一部分是抢占式调度,抢占式的检查点都是调用的cond_resched实现的(下面再详细分析这个函数).直接通过need_resched()来调用schedule和cond_resched的地方不是特别多.
c)直接在一些路径调用cond_resched实现的抢占式检查点.
TIF_NEED_RESCHED_DELAYED: 这个是RT linux patches set进行的扩展, 对应一个need_resched_delayed,然而几乎没有通过这个检查函数实现的检查点. 而preempt_check_resched_delayed()通过被wait queue的wake_up和complete间接的被广泛应用.
trigger :对应检查点,必须有地方trigger上述的检查点.
—- 2.4.18
2.4中trigger比较有限. 最重要的是时钟中断的update_process_times, 监视p->counter,等进程消耗完时间片就触发对这个进程的一次调度,其次就是 schedule_tail->reschedule_idle 在每次调度完成之后试图给prev找到一个合适的CPU去运行, 通过IPI触发另外一个cpu重新调度. 还有就是较少运行的sys_sched_yield,setscheduler.
—-2.6.25.4-rt3
TIF_NEED_RESCHED :
设置这个标志的函数主要有两个: resched_task(),set_tsk_need_resched().主要是resched_task,而resched_task的调用者 check_preempt_curr更是通过:try_to_wake_up/wake_up_new_task/pull_task /__migrate_task 这些被广泛使用的函数, 从而分布在内核中大量的检查点有机会抢占进程.
对应2.4, 最典型的trigger点是hrtick()->curr->sched_class->task_tick->..->set_tsk_need_resched.
TIF_NEED_RESCHED_DELAYED:
对应这个检查点的trigger几乎没有. 看来要fade out了.
直接调用schedule:
区别不大.
cond_resched:这个函数在内核实现很多检查点:
当前进程需要被抢占,且不是处PREEMPT_ACTIVE的环境下,即防止schedule() -> reacquire_kernel_lock() -> down() -> might_sleep()->cond_resched这个循环. 参考
http://mail.nl.linux.org/kernelnewbies/2007-02/msg00311.htmlend