【Linux 内核】调度器 ② ( sched_class 调度类结构体源码 | 源码路径 linux-5.6.18\kernel\sched\sched.h )





一、调度器



上一篇博客 【Linux 内核】调度器 ( 调度器概念 | 调度器目的 | 调度器主要工作 | 调度器位置 | 进程优先级 | 抢占式调度器 | Linux 进程状态 | Linux 内核进程状态 ) 介绍了 " 调度器 " 概念 ,

Linux 内核的 " 进程调度 " 是按照 设计好的调度算法 安排的 , 该算法对应的功能模块 称为 " 调度器 " , 英文名称是 Scheduler ;

" 调度器 " 可以 切换 " 进程状态 " , 主要是 " 就绪状态 "" 执行状态 " 这两个状态之间相互切换 ;

" 抢占式调度器 " 概念 : 如果 " 调度器 " 支持 " 就绪状态 " " 运行状态 " 之间可以相互转换 , 则该调度器称为 " 抢占式调度器 " ;





二、sched_class 调度类结构体



Linux 内核源码 linux-5.6.18\kernel\sched\sched.h 中 , 定义的 struct sched_class 调度类结构体 , 就是 " 调度器 " 对应的类 ;

struct sched_class 调度类结构体源码如下 :

struct sched_class {
	const struct sched_class *next;

#ifdef CONFIG_UCLAMP_TASK
	int uclamp_enabled;
#endif

	void (*enqueue_task) (struct rq *rq, struct task_struct *p, int flags);
	void (*dequeue_task) (struct rq *rq, struct task_struct *p, int flags);
	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);

	struct task_struct *(*pick_next_task)(struct rq *rq);

	void (*put_prev_task)(struct rq *rq, struct task_struct *p);
	void (*set_next_task)(struct rq *rq, struct task_struct *p, bool first);

#ifdef CONFIG_SMP
	int (*balance)(struct rq *rq, struct task_struct *prev, struct rq_flags *rf);
	int  (*select_task_rq)(struct task_struct *p, int task_cpu, int sd_flag, int flags);
	void (*migrate_task_rq)(struct task_struct *p, int new_cpu);

	void (*task_woken)(struct rq *this_rq, struct task_struct *task);

	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 (*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 by
	 * rq->lock. They are however serialized by p->pi_lock.
	 */
	void (*switched_from)(struct rq *this_rq, struct task_struct *task);
	void (*switched_to)  (struct rq *this_rq, struct task_struct *task);
	void (*prio_changed) (struct rq *this_rq, struct task_struct *task,
			      int oldprio);

	unsigned int (*get_rr_interval)(struct rq *rq,
					struct task_struct *task);

	void (*update_curr)(struct rq *rq);

#define TASK_SET_GROUP		0
#define TASK_MOVE_GROUP		1

#ifdef CONFIG_FAIR_GROUP_SCHED
	void (*task_change_group)(struct task_struct *p, int type);
#endif
};

在这里插入图片描述

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux内核中的进程调度被称为“调度”,其源代码位于`kernel/sched/`目录下。调度内核的一部分,它控制着在多个进程之间分配CPU时间片的方式。在这个过程中,调度需要考虑多个因素,例如进程优先级、进程所需的资源、进程等待的时间以及系统负载等。 下面是对Linux内核进程调度的源代码进行简要的解析: 1. 调度初始化 调度初始化函数为`sched_init()`,它负责初始化调度的各种数据结构和变量。在这里,调度将创建一个名为`init_task`的内核线程,该线程是系统中的第一个进程调度还会初始化各种调度相关的数据结构和变量,例如CPU负载平衡进程优先级队列等。 2. 进程调度 进程调度函数为`sched_schedule()`,它被调用以选择下一个要运行的进程调度使用了一种多级反馈队列调度算法,其中进程根据它们的优先级被分配到不同的队列中。调度将首先从优先级最高的队列中选择下一个要运行的进程。如果该队列为空,则调度将继续选择下一个队列,直到找到非空队列为止。如果所有队列都为空,则调度将选择一个空闲的CPU,并将当前进程移到该CPU上。 3. 进程优先级 进程的优先级是一个重要的因素,它决定了进程在被分配CPU时间片时的顺序。Linux内核中,进程的优先级范围从0到139,其中0是最高优先级,139是最低优先级。优先级为0的进程是实时进程,可以通过`sched_setscheduler()`函数设置。其他进程的优先级由调度动态调整,通常根据进程的历史运行时间、进程型、进程等待时间等因素进行计算。 4. CPU负载平衡 当系统中有多个CPU时,调度还需要考虑如何平衡CPU的负载。为此,调度将在不同的CPU之间移动进程,以确保每个CPU的负载尽可能相等。调度会定期扫描系统中的所有CPU,查找负载最轻的CPU,并将某些进程从其他CPU移动到该CPU上。 5. 调度策略 调度还支持不同的调度策略,例如完全公平调度(CFS)、实时调度(RT)、轮转调度(RR)等。不同的调度策略适用于不同的场景,例如CFS适用于普通的任务,而RT适用于实时任务。调度策略可以通过`sched_setscheduler()`函数进行设置。 以上是对Linux内核进程调度的简要介绍和源代码解析。由于调度的复杂性,这里仅介绍了一些基本概念和代码实现。如果您对此感兴趣,建议仔细阅读相关文档和源代码。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值