IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 内核调度器原理与分析 -> 正文阅读

[数据结构与算法]内核调度器原理与分析

介绍

内核中针对task_struct进程描述符专门安排有序执行的模块叫调度器
调度器作用:
1 cpu中央处理器专门管理时间
2 通过进程优先级为依据专门分配时间

当在运行的过程中,某个进程的时间片到了或者缺少某个条件就会发生上下文切换,cpu重新切换一个进程。

调度类

1 调度类结构体sched_class:
内核中提供了一个专门用来调度的进程的类接口sched_class
在内核中,系统中有多个调度类,按调度优先级连接成链表。
kernel/sched/sched.h文件中

struct sched_class {
	// 系统当中有多个调度类,按照调度优先级排成一个链表;下一个优先级的调度类
	const struct sched_class *next;
	// 将进程task_struct加入到执行队列当中,将调度实体(进程)存放到红黑树中,
	// 并且对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);
	// 选择下一个要运行的进程
	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函数,它可能引起进程切换,将驱动运行时running抢占
	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);
	// 转用于进程切换操作
	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);
#ifdef CONFIG_FAIR_GROUP_SCHED
	void (*task_move_group) (struct task_struct *p);
#endif
};

常用的接口:
enqueue_task:向就绪队列加一个进程,实体添加到红黑树,ns_running++
dequeue_task:将一个进程从就绪队列删除,当某个任务退出可运行状态调用该函数它将从红黑树去掉对应调度实体。
yield_task:在进程想要资源放弃对处理器控制权调用,在sched_yield系统调用,会调用内核api去操作。
check_preempt_curr:抢占式系统才会用到,检查当前运行任务是否被抢占。
pick_next_task:选择下一个要运行的任务
put_prev_task: 将进程放回运行队列中

2 具体调度类:
内核中提供了5种调度类分别是
dl_sched_class: deadline调度类
rt_sched_class:实时调度类 针对实时进程
fair_sched_class:公平调度类 针对普通进程
idle_sched_class:空闲调度类 针对空闲进程
stop_sched_class: 停机调度类 针对停机进程

3: 调度类的组织形式
每个cpu第一个pid=0线程,swapper是一个静态线程,调度类属于idle_sched_class
linux调度的核心:选择一个合适的task运行,会按照优先级顺序遍历调度类 pick_next_task函数
在这里插入图片描述

调度实体

在内核进程描述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;
#ifdef CONFIG_CGROUP_SCHED
	struct task_group *sched_task_group;
#endif
	struct sched_dl_entity dl;
	......

进程根据自己是实时的,还是普通的类型,通过这个成员变量,将自己挂在某一个数据结构里面,和其他的进程排序,等待被调度。如果这个进程是个普通进程,则通过 sched_entity,将自己挂在这棵红黑树上

调度策略

linux内核调度策略源码:/include/uapi/linux/sched.h。
提供了6种调度策略。

#define SCHED_NORMAL 0 // 用于普通进程,通过cfs实现
#define SCHED_FIFO 1 // 先入先进先出调度算法(实时调度策略),相当于优先级先到先服务,高优先级可抢占优先
#define SCHED_RR 2 //轮流调度算法(实时调度策略)
#define SCHED_BATCH 3 // 相当于sched_normal分化版本,采用分时策略,根据动态优先级,分配cpu运行需要资源
// SCHED_ISO 4 预留未显示
#define SCHED_IDLE 5 // 优先级最低,相当于系统空闲才跑这类进程
#define SCHED_DEADLINE 6 // 新支持实时进程调度策略,针对突发性计算

总结

读了这么多代码以及过不好这一生,直接上图,一图胜千言
在这里插入图片描述

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-04-23 11:02:21  更:2022-04-23 11:03:20 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 7:44:59-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码