嵌入式实时操作系统的设计与开发(调度策略学习)

news2025/1/24 22:28:39

将调度分为两层,上层为策略,下层为机制,并且采用策略与机制分离的设计原则,可以方便灵活地扩展调度策略,而不改变底层的调度机制。

调度策略就是如何确定线程的CPU、优先级prio等参数,线程是按照FIFO,还是分时策略来调度。对某些线程要特殊调度处理,然后根据相应操作来初始化线程。一种策略就对应一种线程。

线程调度分层结构

在这里插入图片描述

调度策略本质就是调度算法,即确定任务执行顺序的规则,调度策略目前包括通用策略、分时策略、周期策略和RM策略,用户还可以自行扩展新的调度策略。

用户创建线程时,需要指定某种调度策略,并找到该调度策略对应的策略控制块,再为TCB成员赋值。

调度策略分类

  1. 普通线程(通用策略创建的线程)。这种线程,需要人为指定CPU、优先级信息,通过acoral_create_thread创建。
  2. 分时线程(分时策略创建的线程)。aCoral支持相同优先级的线程,对于相同优先级的线程,默认采用FIFO的方式调度,因此,当用户需要以分时的方式和其他线程共享CPU资源时,可以将该线程设置为分时线程。若用分时调度策略创建线程,应注意以下两点:
    (1)只存在相同优先级的分时策略,不同优先级线程之间不存在所谓的分时策略,它们是按优先级抢占策略来调度的。
    (2)必须都是分时线程。
  3. 周期线程(周期策略创建的线程)。这种线程需要每隔一个固定时间就要执行一次,如信号采集系统有一个采样周期,每隔一段时间就要采集一路信号。
  4. RM线程(RM策略创建的线程)。RM是一种可以满足任务截止时间的强实时调度算法,这种策略需要周期性线程策略支持。在配置成支持RM的线程策略,就必须同时配置支持周期性策略。
  5. POSIX线程(POSIX策略创建的线程)。POSIX线程属于非实时线程,也是一个标准,这类线程的主要特点是越公平越好。让aCoral支持POSIX标准有两个出发点,一是实现最大公平,二是实现POSIX标准。为了实现最大公平,这种线程又有了一个自己的调度算法:电梯调度算法。

描述调度策略

typedef struct{
	acoral_list_t list; //策略链表结点,用于将策略挂到策略链表上去,用于把各个调度策略串到一个链表上,创建线程找策略的时候去这个链表上,根据策略名找,有几个策略就有几个结点
	acoral_u8 type; //策略类型,比如COMM
	_id (*policy_thread_init)(acoral_thread_t *, void (*route)(void *args), void *,void *); //策略线程初始化函数,用于确定线程的CPU、优先级等参数。
	void (*policy_thread_release)(acoral_thread_t *); //某种策略的释放函数,用于消灭线程时调用
	void (*delay_deal)(void); //与延时相关的处理函数,如period、slice等策略都要用到类似的延时机制。
	char *name; //用于传递某种调度策略所需要的参数。每种策略对应一种数据结构,用来保存线程的参数,比如普通策略的参数只有CPU、prio。
}acoral_sched_policy_t;
//普通线程调度相关的数据
typedef struct{
	unsigned char prio; 
	unsigned char prio_type; //优先级类型,有BASE_PRIO,根据系统需要在创建线程时进行调整;ABSOLUTE,表示优先级设定是多少就多少
}comm_policy_data_t
//周期策略数据块
typedef struct{
	unsigned char prio;
	unsigned char prio_type;
	unsigned int time;//线程周期,单位毫秒
}period_polciy_data_t;

查找调度策略

当用户想根据某种调度策略创建线程时,须根据TCB的policy成员值从策略控制块链表中查找相应的结点,将信息取出赋值给TCB成员。

acoral_list_t policy_list;
acoral_sched_policy_t *acoral_get_policy_ctrl(unsigned char type){
	acoral_list_t *tmp,*head;
	acoral_sched_policy_t *policy_ctrl;
	head = &policy_list;
	tmp = head;
	for(tmp=head->next;tmp!=head;tmp=tmp->next)
	{
		policy_ctrl = list_entry(tmp,acoral_sched_policy_t,list);
		if(policy_ctrl->type == type)
			return policy_ctrl;
	}
	return NULL;
}

当创建一个结构体变量时,该结构体变量在内存中会占据一段连续的内存空间,每个成员变量都在这个内存块中有自己的地址偏移。

结构体指针实际上是一个执行结构体内存块起始地址的指针。通过这个指针,可以访问结构体内存块中的各个成员变量。

  1. 内存布局:结构体的成员变量在内存中是按照它们在结构体定义中的顺序排列的,成员变量之间是连续存储的。
  2. 操作符->,结构体指针用->来访问结构体成员
struct Point{
	int x;
	int y;
};

struct Point p1;
struct Point *ptr = &p1;

ptr->x = 10;
ptr->y = 20;

p1.x = 5;
p1.y = 15;

注册调度策略

若要扩展新的调度策略并且生效,须进行注册,只有注册后,用户才能通过此策略创建特定类型的线程。
注册就是将用户自己定义的调度策略挂载到策略控制链表上,放在队尾。

void acoral_register_sched_policy(acoral_sched_policy_t *policy){
	acoral_list_add2_tail(&policy->list, &policy_list);
}

通用调度策略是在什么时候注册的呢?
在进行通用调度策略初始化comm_policy_init()时注册

acoral_sched_policy_t comm_policy;
void comm_policy_init()
{
	comm_policy.type = ACORAL_SCHED_POLICY_COMM;
	comm_policy.policy_thread_init = comm_policy_thread_init;
	comm_policy.policy_thread_release = NULL;
	comm_policy.delay_deal = NULL;
	comm_policy.name = "comm";
	acoral_register_ched_policy(&comm_policy);
}
acoral_list_t period_delay_queue; //周期线程专用延时队列,只要是周期线程,就会被挂载到这个队列上,延时时间就是周期,每次周期过后重新挂载
acoral_sched_policy_t period_policy;
void period_policy_init(void)
{
	acoral_init_list(&period_delay_queue);
	period_policy.type=ACORAL_SCHED_POLICY_PERIOD;
	period_policy.policy_thread_init=period_policy_thread_init;
	period_policy.policy_thread_release=period_policy_thread_release;
	period_policy.delay_deal=period_delay_deal;
	period_policy.name="period";
	acoral_register_sched_policy(&period_policy);
}

通用调度策略初始化又是在什么时候被调用的呢?

void sched_policy_init()
{
	acoral_init_list(&policy_list);
	comm_policy_init();
#ifdef CFG_THRD_PERIOD
	period_policy_init();
#endif
}
void acoral_thread_sys_init()
{
	acoral_sched_mechanism_init();
	acoral_sched_policy_init();
}
void acoral_sched_machanism_init()
{
	acoral_thread_pool_init();
	acoral_thread_runqueue_init();
	acoral_init_list(&acoral_threads_queue); //全局所有线程队列
}
acoral_pool_ctr_ acoral_thread_pool_ctrl;
void acoral_thread_pool_init()
{
	acoral_thread_pool_ctrl.type = ACORAL_RES_THREAD;
	acoral_thread_pool_ctrl.size = sizeof(acoral_thread_t);
	if(CFG_MAX_THREAD > 20)
		acoral_thread_pool_ctrl.num_per_pool = 20;
	else
		acoral_thread_pool_ctrl.num_per_pool = CFG_MAX_THREAD;
	acoral_thread_pool_ctrl.max_pools = CFG_MAX_THREAD/acoral_thread_pool_ctrl.num_per_pool;
	acoral_pool_ctrl_init(&acoral_thread_pool_ctrl);
}
void acoral_pool_ctrl_init(acoral_pool_ctrl_t *pool_ctrl)
{
	unsigned int size;
	pool_ctrl->free_pools = &pool_ctrl->list[0];
	pool_ctrl->pools = &pool_ctrl->list[1];
	pool_ctrl->num = 0;
	acoral_init_list(pool_ctrl->pools);
	acoral_init_list(pool_ctrl->free_pools);
	//调整pool的对象个数最大化利用分配了的内存
	size = acoral_malloc_adjust_size(pool_ctrl->size * pool_ctrl->num_per_pool);
	if (size < pool_ctrl->size)
	{
		pool_ctrl->num_per_pool = 0;
	}
	else
	{
		pool_ctrl->num_per_pool = size / pool_ctrl->size;
		acoral_create_pool(pool_ctrl); // 先创建一个资源池,后面如果一个池子不够了,那在不超过这类资源的max_pool的条件下再创建新的池子
	}
}
void acoral_thread_runqueue_init()
{
	acoral_rdy_queue_t *rdy_queue;
	rdy_queue = &acoral_ready_queues;
	acoral_prio_queue_init(rdy_queue);
}

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

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

相关文章

Sui第六轮资助:15个项目共获得106万美元的资助

近日&#xff0c;Sui基金会宣布了15个项目获得共计106万美元的资助&#xff0c;用于构建项目以推动Sui的采用和发展。要获得资助&#xff0c;项目必须提交详细描述其正在构建的内容、逐项预算、关键里程碑、团队经验以及对Sui社区预期贡献的提案。 获得资助的15个项目致力于跨…

WPF 用户控件依赖注入赋值

前言 我一直想组件化得去开发WPF&#xff0c;因为我觉得将复杂问题简单化是最好的 如何组件化开发 主窗口引用 <Window x:Class"WpfApp1.MainWindow"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://schemas.…

如何将前后端分离项目部署到本地的Docker Desktop容器运行并且访问

文章目录 前言 完成了客户的一个前后端分离项目&#xff0c;要求部署到客户电脑上去展示&#xff0c;那肯定不能直接把代码弄上去跑呀~~~&#xff0c;于是我就想把他们都打包部署到本地的docker容器里面&#xff0c;方便运行和访问&#xff0c;so&#xff0c;以下内容就详细介…

封装canvas选择区域的组件

大家好&#xff0c;我是南宫&#xff0c;最近我刚完成了一个canvas相关组件的封装。我个人其实很怕canvas和地图&#xff0c;就感觉这里有很复杂的操作&#xff0c;搞不懂&#xff0c;所以这次封装完了以后&#xff0c;决定写一篇博客来记录。 首先我先简单介绍一下这个组件的…

【仙逆】王林极限跑酷,藤厉自食恶果,仙逆战斗获好评,张虎命运被改写

Hello,小伙伴们&#xff0c;我是小郑继续为大家深度解析国漫资讯。 最新一集《仙逆》已经更新&#xff0c;相信很多小伙伴都已经先睹为快&#xff0c;在击杀了白展之后&#xff0c;张虎和王林担心其师傅即墨老人报复&#xff0c;因此躲到看似安全的藤家城&#xff0c;以为那里有…

MySQL学习(三)——多表连接查询

文章目录 1. 多表关系1.1 一对多1.2 多对多1.3 一对一 2. 概述2.1 数据准备2.2 简单查询2.3 分类 3. 内连接4. 外连接5. 自连接5.1 自连接查询5.2 联合查询 6. 子查询6.1 概念6.2 标量子查询6.3 列子查询6.4 行子查询6.5 表子查询 1. 多表关系 项目开发中&#xff0c;在进行数…

UE5 运行时生成距离场数据

1.背景 最近有在运行时加载模型的需求&#xff0c;使用DatasmithRuntimeActor可以实现&#xff0c;但是跟在编辑器里加载的模型对比起来&#xff0c;室内没有Lumen的光照效果。 图1 编辑器下加载模型的效果 图2 运行时下加载模型的效果 然后查看了距离场的数据&#xff0c;发现…

leetcode-48.旋转图像

1. 题目 leetcode题目链接 给定一个 n n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。 你必须在 原地 旋转图像&#xff0c;这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。 2. 编程 矩阵转置&#xff1a; 遍历矩阵&#x…

EKP接口开发Webservice服务和Restservice服务以及定时任务Demo

继承com.landray.kmss.sys.webservice2.interfaces.ISysWebservice&#xff0c;同时在接口上使用WebService注解将其标识为WebService接口 package com.landray.kmss.third.notify.webservice;import com.alibaba.fastjson.JSONObject; import com.landray.kmss.sys.webservic…

CAD图形导出为XAML实践

文章目录 一、前言二、方法与实践2.1 画出原图&#xff0c;借第三方工具导出至指定格式2.2 CAD导出并转换2.3 两种方法的优劣2.3.1 直接导出代码量大2.3.2 导入导出需要调参 三、总结 一、前言 上位机通常有一个设备/场景界面&#xff0c;该界面用于清晰直观地呈现设备状态。 …

线程通信java

有包子 不做了 唤醒别人等地自己 this.notifyAll(); this.wait() package TheadCpd;public class TheadCpd {//目标&#xff1a;了解线程通信public static void main(String[] args) {//需求&#xff1a;3个人生产或者线程 负责生产包子 每个线程生产1个包子放桌子上// 2…

Pytorch:cat、stack、squeeze、unsqueeze的用法

Pytorch&#xff1a;cat、stack、squeeze、unsqueeze的用法 torch.cat 在指定原有维度上链接传入的张量&#xff0c;所有传入的张量都必须是相同形状 torch.cat(tensors, dim0, *, outNone) → Tensor tensor:相同形状的tensor dim:链接张量的维度&#xff0c;不能超过传入张…

C++对象模型(10)-- 虚函数2

1、虚函数表、虚函数表指针的创建时机 我们知道虚函数表是属于类的&#xff0c;而虚函数表指针是属于对象的。在编译的时候&#xff0c;编译器会往类的构造函数中插入创建虚函数表指针的代码。同样&#xff0c;在编译期间编译器也为每个类确定好了对应的虚函数表的内容。 虚函…

巡检系统是什么?设备巡检系统有什么用?

在现今这个高度自动化的时代&#xff0c;许多企业的设备规模日益扩大&#xff0c;设备巡检工作也变得越来越重要。它不仅是保证企业设备正常运行的重要环节&#xff0c;也是维护生产安全和提升运营效率的关键。那么&#xff0c;如何有效地进行设备巡检呢&#xff1f;答案就是—…

CSS Vue/RN 背景使用opacity,文字在背景上显示

Vue <div class"training_project_tip"> <div class"tip">展示的文字</div> </div> .training_project_tip { font-size: 12px; font-weight: 400; text-align: left; color: #ffffff; margin-top: 8px; position: relative; dis…

6.自定义相机控制器

愿你出走半生,归来仍是少年&#xff01; Cesium For Unity自带的Dynamic Camera,拥有优秀的动态展示效果&#xff0c;但是其对于场景的交互方式用起来不是很舒服。 通过模仿Cesium JS 的交互方式&#xff0c;实现在Unity中的交互&#xff1a; 通过鼠标左键拖拽实现场景平移通过…

模式植物背景基因集制作

一边学习&#xff0c;一边总结&#xff0c;一边分享&#xff01; 写在前面 关于GO背景基因集文件的制作&#xff0c;我们在很早以前也发过。近两天&#xff0c;自己在分析时候&#xff0c;也是被搞了头疼。想重新制作一份GO背景基因集&#xff0c;进行富集分析。但是结果&…

Cpolar+Inis结合在Ubuntu上打造出色的博客网站,快速上线公网访问

文章目录 前言1. Inis博客网站搭建1.1. Inis博客网站下载和安装1.2 Inis博客网站测试1.3 cpolar的安装和注册 2. 本地网页发布2.1 Cpolar临时数据隧道2.2 Cpolar稳定隧道&#xff08;云端设置&#xff09;2.3.Cpolar稳定隧道&#xff08;本地设置&#xff09; 3. 公网访问测试总…

编辑器功能:用一个快捷键来【锁定】或【解开】Inspector面板

一、需求 我有一个脚本&#xff0c;上面暴露了许多参数&#xff0c;我要在场景中拖物体给它进行配置。 如果不锁定Inspector面板的话&#xff0c;每次点击物体后&#xff0c;Inspector的内容就是刚点击的物体的内容&#xff0c;而不是挂载脚本的参数面板。 二、 解决 &…

适老化改造监管平台

文章目录 前言一、首页二、客户管理三、评估管理四、施工管理五、验收管理总结 前言 适老化改造监管平台是指一种为老年人住房进行适老化改造所建立的监管平台。该平台可以辅助政府监管相关企业或个人为老年人住房进行适老化改造的工作&#xff0c;确保改造符合相关标准和规定…