Linux内核必懂知识—调度器分析及完全公平调度器CFS

调度器分析

调度器

  • 内核中安排进程执行的模块,用以切换进程状态。

  • 做两件事:选择某些就绪进程来执行;打断某些执行的进程让其变为就绪状态。

  • 分配CPU时间的基本依据:进程优先级。 上下文切换(context switch):将进程在CPU中切换执行的过程,内核承担 此任务,负责重建和存储被切换掉之前的CPU状态。

调度类sched_class结构体与调度类

sched_class结构体表示调度类,定义在kernel/sched/sched.h。

  • 成员解析 ecqueue_task:向就绪队列添加一个进程,某个任务进入可运行状态时,该函数将会被调用,它将调度实体放入到红黑树中。 dequeue_task:将一个进程从就绪队列中进行删除,当某个任务退出可运行状态时调用该函数,它将从红黑树中去掉对应调度实体。 yield_task:在进程想要资源放弃对处理器的控制权时,可食用在sched_yield系统调用,会调用内核API去处理操作。 check_preempt_curr:检查当前运行任务是否被抢占。 pick_next_task:选在接下来要运行的最合适的实体(进程)。 put_prev_task:用于另一个进程代替当前运行的进程。 set_curr_task:当任务修改它的调用类或修改它的任务组时,将调用这个函数。 task_tick:在每次激活周期调度器时,由周期性调度器调用。

  • 源码注释

// 系统当中有多个调度类,按照调度优先级排成一个链表,下一个优先级调度类
	const struct sched_class *next;
	// 将进程加入到执行队列当中,即将调度实体(进程)存放到红黑树中,并对nr_running变量自动加1
	void (*enqueue_task) (struct rq *rq, struct task_struct *p, int flags);
	// 从执行队列当中删除进程,并对nr_running变量自动减1
	void (*dequeue_task) (struct rq *rq, struct task_struct *p, int flags);
	// 放弃CPU执行权,实际上该函数执行先出队后入队,在这种情况下,它直接将调度实体放在红黑树的最右端
	void (*yield_task) (struct rq *rq);
	bool (*yield_to_task) (struct rq *rq, struct task_struct *p, bool preempt);
	// 用于检查当前进程是否可以被新的进程抢占
	void (*check_preempt_curr) (struct rq *rq, struct task_struct *p, int flags);

	/*
	 * It is the responsibility of the pick_next_task() method that will
	 * return the next task to call put_prev_task() on the @prev task or
	 * something equivalent.
	 *
	 * May return RETRY_TASK when it finds a higher prio class has runnable
	 * tasks.
	 */
	// 选择下一个应该要运行的进程
	struct task_struct * (*pick_next_task) (struct rq *rq,
						struct task_struct *prev);
	// 将进程放回到运行队列当中 
	void (*put_prev_task) (struct rq *rq, struct task_struct *p);

#ifdef CONFIG_SMP
	// 为进程选择一个合适的CPU
	int  (*select_task_rq)(struct task_struct *p, int task_cpu, int sd_flag, int flags);
	// 迁移任务到另一个CPU
	void (*migrate_task_rq)(struct task_struct *p);
	// 专门用户唤醒进程	
	void (*task_waking) (struct task_struct *task);
	void (*task_woken) (struct rq *this_rq, struct task_struct *task);
	// 修改进程在CPU的亲和力
	void (*set_cpus_allowed)(struct task_struct *p,
				 const struct cpumask *newmask);
	// 启动运行队列
	void (*rq_online)(struct rq *rq);
	// 禁止运行队列
	void (*rq_offline)(struct rq *rq);
#endif
	// 当进程改变它的调度类或进程组时被调用
	void (*set_curr_task) (struct rq *rq);
	// 调用自己time_tick函数,可能引起进程切换,将驱动运行时抢占
	void (*task_tick) (struct rq *rq, struct task_struct *p, int queued);
	// 当进程创建时候调用,不同调度策略的进程初始化不一样
	void (*task_fork) (struct task_struct *p);
	// 进程退出时会使用
	void (*task_dead) (struct task_struct *p);

	/*
	 * The switched_from() call is allowed to drop rq->lock, therefore we
	 * cannot assume the switched_from/switched_to pair is serliazed
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值