linux调度器(三)——周期性调度器与CFS

注:这里并没有详细分析到每个内部函数,如果要了解这些细节的话,可以看后面的 OTHER CFS CLASS APICFS主要的内部函数。
   
周期性调度器在调度框架上由 scheduler_tick完成:在每一个cpu的时钟周期都触发一次该函数调用,它更新运行队列的时钟及load,然后调用当前进程的调度器类的周期调度函数。
	update_rq_clock(rq); /* 更新运行队列的时钟rq->clock*/  
	update_cpu_load_active(rq); /* 更新运行队列load,本质是将数组中先前存储的负荷值向后移动一个位置,将当前负荷记入数组的第一个位置 */  
	curr->sched_class->task_tick(rq, curr, 0);
我们再来看一下CFS调度器类的周期调度函数( task_tick_fair),该函数是对 entity_tick的组调度的一个封装(因为只有真正的task的se才会在cpu上运行,而group的se是不会在cpu上运行的,所以这里参数的se就是一个task,然后对从它到它所在的组的根的所有group se调用entity_tick),所以我们直接来看一下 entity_tick函数:
update_curr(cfs_rq); //完成当前se(这个se可以是task或group)的执行时间,虚拟时间,cfs_rq的相应时间及统计的更新:curr->exec_start=now;curr->sum_exec_runtime+=delta_exec;及curr->vruntime+= calc_delta_fair();更新cfs_rq的min_vruntime.其中delta_exec表示实质执行的时间,而calc_delta_fair则计算delta_exec相对应的虚拟时间,即delta_fair={if se->load.weight != NICE_0_LOAD return delta_exec; else return delta_exec *NICE_0_LOAD/se.load->weight},可以看到当该se是0优先级的话,那么它的虚拟时间等于实质执行的物理时间,否则如果该se的load越大那么它的虚拟时间就越小,这也是为什么load越大的进程能够执行的时间越多——它的虚拟时间增长的越慢

	update_entity_shares_tick(cfs_rq); //这个函数只有对于SMP才有作用,所以我们这里先不分析

#ifdef CONFIG_SCHED_HRTICK  //HRTICK情况,不知道干嘛 
	if (queued) {
		resched_task(rq_of(cfs_rq)->curr);
		return;
	}
	if (!sched_feat(DOUBLE_TICK) &&
			hrtimer_active(&rq_of(cfs_rq)->hrtick_timer))
		return;
#endif

	if (cfs_rq->nr_running > 1 || !sched_feat(WAKEUP_PREEMPT)) //可运行的大于1,或者不支持WAKEUP_PREEMPT,后面这个条件在后来的版本已经被去掉了
		check_preempt_tick(cfs_rq, curr); //该函数用于检查当前进程是否运行了足够长的时间(实质运行时间大于sched_slice理想运行时间或者当前运行队列最左边的se到现在的等待的时间已经超过curr理想应该运行的时间),如果出现了上面的情况则调用resched_task将该进程设置为TIF_NEED_RESCHED,即可调度的;如果运行时间小于sysctl_sched_min_granularity(最小执行时间)或者内核不允许WAKEUP_PREEMPT(内核允许的调度特性在/proc/sys/kernel/sched_features定义WAKEUP_PREEMPT使用第3 bit),则直接返回。注意这里的每个判断条件的顺序是非常重要的(前面的更重要):1.如果进程已经运行超过它的理想运行时间那么它将无条件被resched_task;2.如果不支持WAKEUP_PREEMPT那么直接返回不对当前的进行resched_task;3.如果运行的时间小于sysctl_sched_min_granularity那么也直接返回;4.最左边的等待时间大于理想运行时间时resched_task(curr),即要4满足的话,必须当前的执行时间小于它理想运行时间,并且支持WAKEUP_PREEMPT及运行了至少sysctl_sched_min_granularity,最后已经等待的时间大于理想运行时间

可以看到每个时钟都对会当前运行的se进行实质执行时间及虚拟执行时间进行更新,最后检查该进程是否运行的足够长的时间,如果是的话则将它置为TIF_NEED_RESCHED供主调度在适当的时机进行切换。可见周期性调度器还是比较简单,没有涉及到真正的调度任务,只是设置一个重调度请求的标志而已,下面看看主调器,也就是它来响应周期性调度器的 TIF_NEED_RESCHED

图 CFS与周期调度器

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值