linux内核调度子系统随笔(一)

news2024/12/23 11:30:37
调度子系统组件

 

(1) 调度类用于判断接下来运行哪个进程,内核支持不同的调度策略(完全公平调度,实时调度);调度类使得能够以模块化方法实现这些策略;

(2) 在选中将要选择的进程后,必须执行底层任务切换;需要与cpu的紧密交互;

每个进程都刚好属于某一调度类,各个调度类负责管理所属的进程;通用调度器自身完全不涉及进程管理,其工作都委托给调度器类;

1. task_struct的成员

各个进程的task_struct有几个成员与调度相关;

struct task_struct {
...

	int prio, static_prio, normal_prio;
	unsigned int rt_priority;
	const struct sched_class *sched_class;
	struct sched_entity se;
	struct sched_rt_entity rt;

    unsigned int policy;
	cpumask_t cpus_allowed;
};

prionormal_prio表示动态优先级;其中normal_prio表示基于进程的静态优先级和调度策略计算出的优先级; prio中保存了调度器考虑的优先级,

static_prio表静态优先级;静态优先级是进程启动时分配的优先级,它可以用nice和sched_setscheduler系统调用修改;否则在进程运行间保存恒定;

rt_priority表示实时进程的优先级;最低0,最高99;值越大,表明优先级越高;

sched_class表示该进所属的调度器类;

se:表示可调度实体;相当于在struct task_struct结构体中内嵌一个实例;

policy:保存了对该进程应用的调度策略;有以下几种;

#define SCHED_NORMAL        0 //用于普通进程;

//用于实现软实时进程,RR实现了循环方法,FIFO使用先进先出几种机制;
#define SCHED_FIFO        1
#define SCHED_RR        2
#define SCHED_BATCH        3//用于非交互,cpu使用密集的批处理进程;
#define SCHED_IDLE        5/* SCHED_ISO: reserved but not implemented yet */

 辅助函数 static inline int rt_policy(int policy) 和 static inline int task_has_rt_policy(struct task_struct *p)用于判断给出的调度策略(或进程)是否属于实时类;

cpus_allowed是一个位域,在多处理上用来限制进程可以在哪些cpu上运行;sched_setaffinity(pid_t pid, const struct cpumask * in_mask)系统调用函数用于设置该位图;

2. 调度器类

 调度器类提供了通用调度器和各个调度方法间的关联;

struct sched_class {
	const struct sched_class *next;

	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_curr_task) (struct rq *rq);
	void (*task_tick) (struct rq *rq, struct task_struct *p, int queued);
	void (*task_fork) (struct task_struct *p);

	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);
};

next: 成员将各个调度器实例连接起来;

enqueue_task: 向就绪队列添加一个新进程;进程从睡眠态到可运行态发生;

dequeue_task: 将一个进程从就绪队列去除,进程从可运行到不可运行态时就会发生;

yield_task: 在进程想要自动放弃对处理器的控制权时,使用sched_yield系统调用,然后内核调用yield_task;

check_preempt_curr:用一个新唤醒的进程来抢占当前进程;如在wake_up_new_task唤醒新进程时会调用该函数;

check_preempt_curr: 用一个新唤醒的进程抢占当前进程;

pick_next_task: 选择下一个将要运行的进程;

put_prev_task:用另一个进程代替当前进程前调用;

set_curr_task:在进程的调度策略发生变换时调用;

task_tick:每次激活周期性调度器时,由周期性调度器调用;

task_fork:用于建立fork系统调用和调度器的关联;每次新进程建立后,用task_fork通知调度器;

各个调度类都必须提供一个sched_class实例;调度器层次结构:实时进程>完全公平进程>空闲进程

fair_sched_class 表示完全公平调度器实例;
rt_sched_class 表示实时调度器实例;

 3. 就绪队列

核心调度器用于管理活动进程的主要数据结构称为就绪队列; 各个cpu都有自身的就绪队列;各个活动进程只出现在一个就绪队列中;

就绪队列使用struct rq表示:

struct rq {
	/* runqueue lock: */
	raw_spinlock_t lock;

	/*
	 * nr_running and cpu_load should be in the same cacheline because
	 * remote CPUs use both these fields when doing load calculation.
	 */
	unsigned long nr_running;
	#define CPU_LOAD_IDX_MAX 5
	unsigned long cpu_load[CPU_LOAD_IDX_MAX];
	unsigned long last_load_update_tick;

	int skip_clock_update;

	/* capture load from *all* tasks on this cpu: */
	struct load_weight load;
	unsigned long nr_load_updates;
	u64 nr_switches;

	struct cfs_rq cfs;
	struct rt_rq rt;

	unsigned long nr_uninterruptible;

	struct task_struct *curr, *idle, *stop;
	unsigned long next_balance;
	struct mm_struct *prev_mm;

	u64 clock;
	u64 clock_task;

	atomic_t nr_iowait;

	/* calc_load related fields */
	unsigned long calc_load_update;
	long calc_load_active;
};

nr_running: 指定了队列上可运行进程的数目;不考虑优先级和调度类;

load: 提供了就绪队列当前负荷的度量;负荷本质与队列当前活动进程数成正比;

cpu_load: 用于跟踪此前的负荷状态;

cfs和rt是嵌入的子就绪队列,分别用于完全公平调度器和实时调度器;

curr:指向运行的进程的task_struct实例;

idle:指向idle进行的task_struct实例;该进程亦称为idle线程,在无其他可运行进程时执行;

clock: 用于实现就绪队列自身的时钟;

 

系统中所有就绪队列都在runqueues数组中,该数组的每个元素分别对应系统的一个cpu;

DECLARE_PER_CPU(struct rq, runqueues);

#define cpu_rq(cpu)		(&per_cpu(runqueues, (cpu)))
#define this_rq()		(&__get_cpu_var(runqueues))
#define task_rq(p)		cpu_rq(task_cpu(p))
#define cpu_curr(cpu)		(cpu_rq(cpu)->curr)
#define raw_rq()		(&__raw_get_cpu_var(runqueues))

4. 调度实体

用struct sched_entity表示调度实体; 

struct sched_entity {
	struct load_weight	load;		/* for load-balancing */
	struct rb_node		run_node;
	struct list_head	group_node;
	unsigned int		on_rq;

	u64			exec_start;
	u64			sum_exec_runtime;
	u64			vruntime;
	u64			prev_sum_exec_runtime;

	u64			nr_migrations;

    ...
};

load 表示权重,决定实体占队列总负荷的比例;

run_node: 标准的数节点,使得实体可以在红黑树排序;

on_rq: 该实体当前是否在就绪队列上接收调度器调度;

sum_exec_runtime:记录消耗的cpu时间,以用于完全公平调度器; 

prev_sum_exec_runtime:进程被撤销cpu时,sum_exec_runtime值保存到prev_sum_exec_runtime;

由于每个task_struct中都嵌入了sched_entity实例,所以进程是可调度实体; 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/115817.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

信息安全管理体系

环境迁移 Platfor m Ops for AI 作为整合了 DataOps、MLOps、ModelOps 的复杂技术平台,在项目开发时仅使用一套系统无法支撑平台的稳定搭建,往往需要开发系统、集成测试系统、正式 环境系统在项目生命周期 中协作配合。将表、索引、并发程序、配置内容等…

HTML5 新增属性

文章目录HTML5 新增属性公共属性hidden属性draggable属性contenteditable属性data-*属性input元素新增属性autocomplete属性autofocus属性placeholder属性required属性pattern属性form元素新增属性novalidate属性HTML5 新增属性 公共属性 HTML5新增的常见公共属性有4个&#…

在今年的数字生态大会上,云原生数据库前进了一大步

云计算时代,数据库上云已成为产业数字化转型的重要动力。近期,在2022腾讯全球数字生态大会云原生数据库技术探索专场上,腾讯云分享了在云原生数据库领域的技术演进与探索,并就其在不同行业场景中的最佳实践进行了详细讲解&#xf…

【C++初阶】stack、queue和priority_queue的模拟实现

文章目录简介stackqueuepriority_queuestack的模拟实现成员变量emptysizetoppushpopqueue的模拟实现成员变量emptysizetoppushpoppriority_queue的模拟实现成员变量emptysizetoppushpop仿函数完整版代码stack.hqueue.hpriority_queue.htest.cpp简介 stack、queue和priority_qu…

四、SpringBoot Starter组件详解

starter组件实际上就是能够实现自动装配的jar包。 1.starter组件创建流程 假设我现在要集成redis,要拿到redisTemplate对象,怎么做呢? 1.引springboot包; 2.创建RedisTemplate类; 3.写配置类; 4.创建spring.factories文件; 5.打成jar包。 示例如下: 1.创建maven项目…

我的世界MOD制作(2)|| 你的第一个MOD

正文:I. 开发环境配置 我们需要一个带mixin的forge开发环境,这一步相当折磨人,网络不好的话半天时间都得砸这上面,但是不要灰心,过了这个坎接下来基本是顺风顺水。 1. 下载资源 & 修改build.gradle 首先去forge官网…

从三万英尺看全链路灰度

作者:卜比 全链路灰度是微服务领域,很实用的企业级场景下的技术能力。 从本期开始,我们将通过《全链路灰度:自顶向下的方法》的系列文章,由远及近的剖析全链路灰度全貌,系列文章分为 4 篇: 《…

无需数据库的笔记flatnotes

本文完成于 10 月底; 什么是 flatnotes? flatnotes 是一个自托管的、无数据库的笔记 Web 应用程序,它利用文件夹存储 Markdown 文件。 官方演示站点:https://demo.flatnotes.io/ 前言 本文介绍的软件很简单,但是有两…

保姆级教学——Python+Pygame怎么实现吃豆豆游戏

耽搁十几天的时间,我顺利的从阳转阴啦, 以后的日子一切恢复正常,好好工作,积极分享。希望在座的小伙伴阳了的全部健康转阴,没阳的全部不会变阳,新的一年,一切顺顺利利。 不知道最近大家学习得怎…

前端大屏常用的几种适配方案

方 案实现方式优点缺点vm vh1.按照设计稿的尺寸,将px按比例计算转为vw和vh1.可以动态计算图表的宽高,字体等,灵活性较高 2.当屏幕比例跟 ui 稿不一致时,不会出现两边留白情况1.每个图表都需要单独做字体、间距、位移的适配&#x…

磨金石教育摄影技能干货分享|看看大师们如何把“树”拍成艺术品

树,可以说是我们生活中最为常见的物种了。 在不同的地域,不同的气候环境下,生长着不同的树种。 北方的白桦树、杨树、梅花;南方的凤凰花、榕树、梧桐等等。 无论哪个地方的树,都有别样的姿态。 1、相机作画 白雪没有覆…

python实验实践【2】深度学习的python包

python包的管理是使用python进行实验过程中最为重要的一环,很多时候运行他人代码失败的原因是没能按照对方的要求配置python包库。本篇博客重点介绍深度学习场景中python包的管理。 目录python包版本选择python包安装python包版本选择 使用pytorch进行深度学习训练…

AndroidRN的混合集成 下载不了RN的依赖可以看看 好使

一、混合开发 App 混合开发,指的是一个 App 部分功能用 Native 构建,其他功能使用跨端框架进行构建,最常见的场景是,Native 作为一个可工程,其实业务开发使用垮端框架进行开发。目前,比较流行的跨端框架有…

ORB-SLAM3算法学习—双目和单目初始化

0总述 ORB-SLAM3算法中视觉的初始化依旧放在tracking线程中,因此在tracking中没有为imu模式设置单独的初始化函数,而IMU的初始化是在localMapping中实现的。 很有用的参考链接:https://cloud.tencent.com/developer/article/1761043 1双目…

Python 基础教程(1)

1.翻转字符串 def reverseWords(input):# 通过空格将字符串分隔符,把各个单词分隔为列表inputWords input.split(" ")# 翻转字符串# 假设列表 list [1,2,3,4], # list[0]1, list[1]2 ,而 -1 表示最后一个元素 list[-1]4 ( 与 list[3]4 一样…

C++ 使用CLion + LibTorch 调用Python训练的PyTorch模型-MNIST

C++ 使用CLion + LibTorch 调用Python训练的PyTorch模型-MNIST 安装LibTorch 进入pytorch官网地址,选则LibTorch版本将LibTorch安装包解压到libtorch-path目录中,libtorch-path是自定义的LibTorch安装目录。

【SpringCloud Alibaba】Sentinel持久化结合Nacos

在前面学习完Sentinel的流控规则以及Nacos时,就是最后的Sentinel持久化了。需要持久化的原因是因为每次启动Sentinel都会使之前配置的规则就清空了,这样每次都要再去设定规则显得非常的麻烦。 思路就是:将流控规则配置进Nacos服务注册中心中&…

【实时数仓】DWS层之关键词主题表(FlinkSQL)、数据可视化接口、Sugar数据大屏、总成交金额接口实现

文章目录一 DWS层-关键词主题表(FlinkSQL)1 过滤数据2 利用UDTF进行拆分(1)拆分结果(2)Join 表函数 (UDTF)(3)代码3 分组、开窗、聚合计算4 转换为流并写入ClickHouse(1)在ClickHous…

大数据网站攻击实时项目架构

随着互联网的流行,网站安全问题就日益突出,但绝大多数的网站开发与建设公司只考虑正常用户的稳定使用,而对于网站安全方面了解甚少,发现网站安全存在问题和漏洞,其修补方式只能停留在页面代码的删除或者是恢复网站备份…

SpringBoot系列之SpringBoot启动流程详解

文章目录前言一、SpringBoot流程分析-初始化二、SpringBoot流程分析-run总结前言 SpringBoot的启动流程在我们面试的时候会经常被问,接下来我们根据源码来分析了解下SpringBoot是怎么启动的 一、SpringBoot流程分析-初始化 首先对SpringBoot主启动类进行debug&…