【INT的内核笔记】scheduler_tick()源码分析

1. 调用时机

一般会在时钟中断时被调用,作用有:

  • 剥夺时间片耗完的进程的CPU使用权,当然具体细节上没这么简单;
  • 进行定时的CPU间负载均衡处理;

2. 大致流程

  • idle进程(swapper进程)的处理。

    idle进程没有时间片可言,主要思路是如果当前逻辑CPU的可执行队里已有进程,应该尽快调度。

    这里所指的调度还是延时调度,也就是设置TIF_NEED_RESCHED,

    还会有些强制调度之类的处理,细节暂未研究;

  • 实时进程的处理。

    在这版本的源码中,没有调度类的概念,实时进程和普通进程是放在相同的可执行队列的。

    实时进程的调度状况:

    • 如果可执行的话,会一直停留在active队列,

      优先级比所有普通进程高,

      因此如果实时进程没有阻塞,同一逻辑CPU中的普通进程没机会运行;

    • SCHED_RR类型的实时进程在时间片消耗完后,会被放到active队列的末尾,

      并且设置TIF_NEED_RESCHED位,

      因此拥有不小于当前优先级的其他实时进程会被调度到;

    • SCHED_FIFO类型的实时进程,就真的除非被更高优先级的实时进程抢占,

      时钟中断这边并不能让它们让出CPU;

  • 交互式进程的处理

    • 当时间片用完时,

      设置TIF_NEED_RESCHED位;

      但当其比expired队列所有进程优先级都高时,

      并不放入expired队列中,而是重新放入active队列中;

      这是对交互式进程的一种优待处理;

    • 当时间片未用完时,

      交互式进程的时间片会被细分为粒度,当运行完一个粒度后,

      就需要重新调度,也就是设置TIF_NEED_RESCHED位;

      这是对交互式进程的一种削弱,毕竟地位没有实时进程高;

  • 普通非交互式进程的处理

    • 当时间片用完时,

      设置TIF_NEED_RESCHED位,并放入到expired队列中;

    • 当时间片未用完时,不作任何操作;

  • 定时负载均衡

    ​ 在整个函数结束之前执行的一步,对各个CPU进行负载均衡处理。

    ​ 具体有点复杂,会在load_balance()的文章进行大致介绍;

3. 源码注释

/*
 * This function gets called by the timer code, with HZ frequency.
 * We call it with interrupts disabled.
 *
 * It also gets called by the fork code, when changing the parent's
 * timeslices.
 */
/**
 * 维持当前最新的time_slice计数器
 * 每次时钟节拍到来时,scheduler_tick函数将被调用,以执行与调度相关的操作。
 */
void scheduler_tick(void)
{
   
	int cpu = smp_processor_id();
	runqueue_t *rq = this_rq();
	task_t *p = current;

	/**
	 * 把转换为纳秒的TSC的当前值存入本地运行队列的timestamp_last_tick中。这个时间戳由sched_clock获得。
	 */
	rq->timestamp_last_tick = sched_clock();

	// idle进程的处理 //
	if (p == rq->idle) {
   
		/**
		 * wake_priorit
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值