加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

进程调度之schedule()解析

(2016-03-12 10:57:05)
标签:

it

分类: 进程

进程调度之schedule()解析

最重要的是__schedule()函数

schedule()函数的主要目的,就是进行进程调度。

core.c(kernel\sched)

http://s12/mw690/002RQMzZzy703df8LsT8b&690

__schedule()函数:

数据对象:cpuid, rq, current, rq_lock, current_state

 

http://s15/mw690/002RQMzZzy703dgduP48e&690

主要步骤:

1.  禁止内核抢占

2.  获取进程所在cpurq

3.  取消为当前进程运行的高精度计数器(hrtimer

4.  获取rq

5.  更新队列时钟

6.  清除当前进程的need_resched标志

7.  如果当前进程为非运行状态,并且当前非内核抢占:

1)如果当前进程有信号待处理,设置当前进程为就绪状态

2)否则,该进程出对rq

8.  如果当前rq没有可运行进程,则通过load balance从其他cpu搬进程

9.  通知调度器类用另外一个进程代替当前进程

10.通知调度器类选择下一个可运行进程

11.如果下一个可运行进程非当前进程,则执行进程切换

12.否则释放队列锁

13.开启内核抢占

14.如果当前进程被设置need_resched,重复1

static void __sched __schedule(void)

{

         struct task_struct *prev, *next;

         unsigned long *switch_count;

         struct rq *rq;

         int cpu;

 

need_resched:

         preempt_disable(); //关闭内核抢占

         cpu = smp_processor_id();//返回当前处理器的id

         rq = cpu_rq(cpu);// 取该处理器上的运行队列

         rcu_note_context_switch(cpu);//更新全局状态,标识当前CPU发生上下文的切换。

         prev = rq->curr;

 

         schedule_debug(prev);

 

         if (sched_feat(HRTICK))//取消为当前进程运行的hrtimer

                   hrtick_clear(rq);

 

        

         smp_mb__before_spinlock();

         raw_spin_lock_irq(&rq->lock);//锁住该队列

 

         switch_count = &prev->nivcsw;//记录当前进程切换的次数

         if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) {//当前进程非运行状态,并且非内核抢占

                   if (unlikely(signal_pending_state(prev->state, prev))) {//当前进程有信号待处理,设置进程为就绪态

                            prev->state = TASK_RUNNING;

                   } else {

                            deactivate_task(rq, prev, DEQUEUE_SLEEP);//将其从运行队列中删除

                            prev->on_rq = 0;

 

                           

                            if (prev->flags & PF_WQ_WORKER) {

                                     struct task_struct *to_wakeup;

 

                                     to_wakeup = wq_worker_sleeping(prev, cpu);

                                     if (to_wakeup)

                                               try_to_wake_up_local(to_wakeup);

                            }

                   }

                   switch_count = &prev->nvcsw;

         }

         pre_schedule(rq, prev);//通知调度器,即将发生进程切换

         if (unlikely(!rq->nr_running))

                   idle_balance(cpu, rq);

 

         put_prev_task(rq, prev);//通知调度器,即将用另一个进程替换当前进程

         next = pick_next_task(rq);//挑选一个优先级高的任务,即可运行的任务

         clear_tsk_need_resched(prev);//清空TIF_NEED_RESCHED标志

         rq->skip_clock_update = 0;

         if (likely(prev != next)) {//如果两个进程不是同一个进程

                   rq->nr_switches++;//队列切换次数更新

                   rq->curr = next;//将当前进程换成刚才挑选的进程

                   ++*switch_count;//进程切换次数更新

                   context_switch(rq, prev, next); //进程上下文切换

                  

                   cpu = smp_processor_id();

                   rq = cpu_rq(cpu);

         } else

                   raw_spin_unlock_irq(&rq->lock);

         post_schedule(rq);//通知调度类,完成了进程切换

 

         sched_preempt_enable_no_resched();//开启内核抢占

         if (need_resched())//如果该进程被其他进程设置了TIF_NEED_RESCHED,则需要重新调度

                   goto need_resched;

}

pick_next_task()

 

static inline struct task_struct *

pick_next_task(struct rq *rq)

{

         const struct sched_class *class;

         struct task_struct *p;

        

         if (likely(rq->nr_running == rq->cfs.h_nr_running)) {//rq中的进程数等于cfs中的进程数,表明没有实时进程

                   p = fair_sched_class.pick_next_task(rq);//cfs挑选下一个可执行的任务

                   if (likely(p))

                            return p;

         }

         for_each_class(class) {//对于每一个调度类(有高优先级到低优先级)

                   p = class->pick_next_task(rq);

                   if (p)

                            return p;

         }

         BUG();

}

----------------------------------------------------------------------------------------------------------------------------

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有