linux 进程调度 pick_next_task()函数

pick_next_task是进程调度的关键步骤,主要功能是从发生调度的CPU的运行队列中选择一个进程运行。本文主要介绍该函数的实现过程。系统中的调度顺序是:实时进程------->普通进程------>空闲进程。分别从属于三个调度类:rt_sched_class,fair_sched_class和 idle_sched_class(每个cpu都有且只有一个Idle 进程且不会阻塞)。

注:idle进程是所有进程的祖先叫做进程0 ,idle 进程或因为历史的原因叫做swapper 进程。

运行top命令可以查看当前的进程状态。

top

下面介绍函数的具体细节

call tree

/*主动入口*/
schedule(void)---------->
                         | __schedule()
                         |   |
preempt_schedule(void)-->    |-->pick_next_task(struct rq *rq, struct task_struct *prev)
/*内核态抢占的入口*/          
static inline struct task_struct *
pick_next_task(struct rq *rq, struct task_struct *prev)
{
    const struct sched_class *class = &fair_sched_class;
    struct task_struct *p;

    /*
     * Optimization: we know that if all tasks are in
     * the fair class we can call that function directly:
     */
    if (likely(prev->sched_class == class &&
           rq->nr_running == rq->cfs.h_nr_running)) {
        p = fair_sched_class.pick_next_task(rq, prev);
        if (unlikely(p == RETRY_TASK))
            goto again;

        /* assumes fair_sched_class->next == idle_sched_class */
        if (unlikely(!p))
            p = idle_sched_class.pick_next_task(rq, prev);

        return p;
    }

again:
    for_each_class(class) {
        p = class->pick_next_task(rq, prev);
        if (p) {
            if (unlikely(p == RETRY_TASK))
                goto again;
            return p;
        }
    }

    BUG(); /* the idle class will always have a runnable task */
}

pick_next_task()的执行过程大致可以分成两个步骤:

步骤1.检查运行队列中是否含有实时进程,if语句中判断了当前cpu就绪队列中的进程数目是否与普通进程的就绪队列中的进程数目相同,如果相同就说明了系统中全是普通进程,直接通过cfs算法(完全公平调度算法Completely Fair Scheduler)的调度类的pick_next_task_fair函数来从普通进程的就绪队列中寻找进程即可。  

cfs算法(完全公平调度算法)的调度类的pick_next_task_fair函数返回值有三种情况

  • RETRY_TASK:表示有从属于更高优先级调度类的进程被唤醒------------>跳转到步骤2。
  • 空指针:表示没有cfs调度类的进程处于就绪态------------------->在idle调度类中寻找进程。(idle调度类永远非空)
  • struct task 结构体指针:表示选择到一个进程--------------->返回指针

步骤2.遍历调度类的链表,并从中选择一个优先级最高的进程。

在内核中的所有现有调度类是按优先级排列在调度类链表中的。高优先级的调度类指向下较低的优先级调度类。在当前Linux 版本中,其初始流程如下所示

rt_sched_class → fair_sched_class → idle_sched_class → NULL

示意图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值