Linux 2.6.36版本内核分析之schedule()

本文详细分析了Linux 2.6.36内核中的schedule()函数,该函数是内核调度的主要实现,负责进程的切换。文章通过讲解schedule()函数的内部流程,包括获取当前CPU、处理中断、判断进程状态、选择下一个进程等步骤,揭示了Linux内核如何维持系统的并发执行和资源分配。

/*
* schedule() is the main scheduler function.调度主函数,又称主调度
*/
asmlinkage void__schedschedule(void)
{
    struct task_struct *prev, *next;//prev:换出进程标识符,next:换入进程标识符
    unsigned long *switch_count;//对prev的进程切换进行计数
    struct rq *rq;//运行队列
    int cpu;//CPU号

need_resched:
 preempt_disable();//关中断
 cpu = smp_processor_id();//获取执行prev进程的cpu号
 rq = cpu_rq(cpu);//获取cpu号所代表的CPU的运行队列
 rcu_note_context_switch(cpu);//
 prev = rq->curr;//获取运行队列中当前指向的进程,也是即将被换出的进程,进程状态是什么?

 release_kernel_lock(prev);//释放大内核锁
need_resched_nonpreemptible:

 schedule_debug(prev);

 if (sched_feat(HRTICK))
  hrtick_clear(rq);

 raw_spin_lock_irq(&rq->lock);
 clear_tsk_need_resched(prev);

 switch_count = &prev->nivcsw;
 if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) {
  if (unlikely(signal_pending_state(prev->state, prev))) {
   prev->state = TASK_RUNNING;
  } else {
   /*
    * If a worker is going to sleep, notify and
    * ask workqueue whether it wants to wake up a
    * task to maintain concurrency.  If so, wake
    * up the task.
    */
   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);
   }
   deactivate_task(rq, prev, DEQUEUE_SLEEP);
  }
  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);

 if (likely(prev != next)) {
  sched_info_switch(prev, next);
  perf_event_task_sched_out(prev, next);

  rq->nr_switches++;
  rq->curr = next;
  ++*switch_count;

  context_switch(rq, prev, next); /* unlocks the rq */
  /*
   * The context switch have flipped the stack from under us
   * and restored the local variables which were saved when
   * this task called schedule() in the past. prev == current
   * is still correct, but it can be moved to another cpu/rq.
   */
  cpu = smp_processor_id();
  rq = cpu_rq(cpu);
 } else
  raw_spin_unlock_irq(&rq->lock);

 post_schedule(rq);

 if (unlikely(reacquire_kernel_lock(prev)))
  goto need_resched_nonpreemptible;

 preempt_enable_no_resched();
 if (need_resched())
  goto need_resched;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值