400行程序写一个实时操作系统(十):用面向对象思想构建抢占式内核
前言
通过前几章的学习,我们学会了如何为RTOS设计一个合理的内存管理算法。现在,是时候学习设计RTOS内核了。
关于RTOS内核的文章也有很多,但都有一点先射箭再化靶子的意味。要么是代码连篇解释却寥寥无几,要么是要先怎么样再怎么样的说教式教程。并不是说这样的教程不好,而是他们缺乏读者普遍需要的东西,也就是更关键的思想方法!
为此,笔者决定:从我们的需求与应用出发,通过从结果思考过程的方式,使用面向对象的思想,逐步构建一个RTOS的内核。
程序 = 数据结构 + 算法
至于为什么要使用面向对象的思想,是因为面向对象思想本身和程序 = 数据结构 + 算法思想就是相通的,我们可以通过类和对象来表现数据结构,通过方法实现算法,从对象与对象的交互关系来构建,从而实现更加健壮的程序。
另外再借用linus的一句话:“Bad programmers worry about the code. Good programmers worry about data structures and their relationships.”
我们需要实现什么?
如果读者有过使用RTOS的经历,那么请你思考:RTOS实现了什么?带来了怎样的便利?
笔者先提出一点:多线程与优先级带来的实时性
RTOS将应用程序划分为多个独立的任务,也就是多线程。多线程允许同时执行多个任务,提高系统的处理能力和效率。例如,在嵌入式系统中,一个线程可以处理传感器数据,另一个线程可以更新用户界面。
实时性的需求,要求RTOS必须在指定的时间内完成关键任务。
我们创建一个又一个的任务,知道这是一个又一个的线程,它们可以并行执行。设置优先级时,我们知道优先级高的任务会优先执行,从而满足实时性。当我们想让任务同时且更有主次地执行时,我们第一个想到的就是使用RTOS。那么,强大的实时性与同时执行的任务,这就是我们想要实现的结果!但是,我们该如何去实现它呢?
如何实现实时性?
请读者想一想,我们创建任务设置优先级时,往往希望某些任务被优先执行,这是实时性实现的关键,也就是说,会有一个调度器来选择高优先级的任务,因此,我们得到了两个对象:任务和调度器。
调度器对象
通过上图我们可以推断,调度器会选择就绪列表中优先级高的任务。同时,就绪列表经常会发生变化,当优先级最高的任务发生变化,那么调度器还要切换任务,因此,我们得到了下图:
切换任务
切换任务时,我们肯定不希望先前任务的状态丢失,因此需要保存任务状态。线程(任务)切换如下:
1.保存之前运行的线程的上下文
2.选择优先级高的任务
3.调用准备运行的线程的上下文
因此有了下图:
保存任务状态,这部分就涉及到和任务对象的交互了。
任务对象
为了方便管理任务,比如设置优先级啥的,我们肯定需要一个任务控制块,也方便我们把任务挂载到就绪列表中。同时,我们要保存当前状态,也就是说我们需要内存,那么这段内存我们给它命名为栈。
任务控制块
一个任务需要记录任务栈的信息,也就是pxTopOfStack(栈顶)、pxStack(栈起始地址)、self_stack(栈对象)这三个结构体。为了实时性,我们还需要优先级。
把图进一步展开:
现在,我们关键的数据结构已经出来了,请读者写下这些代码,pxCurrentTCB就是当前执行的优先级最高的任务了:
sparrow.cClass(TCB_t)
{volatile uint32_t * pxTopOfStack;unsigned long uxPriority;uint32_t * pxStack;Stack_register *self_stack;
};
typedef TCB_t *TaskHandle_t;__attribute__( ( used ) ) TCB_t * volatile pxCurrentTCB = NULL;
typedef void (* TaskFunction_t)( void * );
栈对象
对于栈对象,我们要保存先前的任务状态,方便下一次任务执行时取出当前任务状态到CPU中,那么任务状态是CPU中的哪些信息呢?答案是寄存器:
以及XPSR,它是非常重要的特殊寄存器:
寄存器包括两部分寄存器,一部分是发生中断时硬件自动帮我们保存的寄存器,另一部分是需要我们手动保存的寄存器。
因此继续展开我们的图:
因此让我们写下代码:
Class(Stack_register)
{//automatic stackinguint32_t r4;uint32_t r5;uint32_t r6;uint32_t r7;uint32_t r8;uint32_t r9;uint32_t r10;uint32_t r11;//manual stackinguint32_t r0;uint32_t r1;uint32_t r2;uint32_t r3;uint32_t r12;uint32_t LR;uint32_t PC;uint32_t xPSR;
};
总结
现在,我们的大蓝图已经构建完毕,各种对象与它们之间的关系已然跃出水面。准备就绪,是时候去实现一个RTOS了!
相关文章:

400行程序写一个实时操作系统(十):用面向对象思想构建抢占式内核
前言 通过前几章的学习,我们学会了如何为RTOS设计一个合理的内存管理算法。现在,是时候学习设计RTOS内核了。 关于RTOS内核的文章也有很多,但都有一点先射箭再化靶子的意味。要么是代码连篇解释却寥寥无几,要么是要先怎么样再怎么…...

C#学习笔记(九)
C#学习笔记(九) 第六章 面向对象编程(一)类与对象、字段与属性一、类与对象正确的理解1. 什么是类?2.什么是对象?3. 类与对象的区别 二、类的基本规范和对象使用1. 类的规范 三、类的访问修饰符(…...

意外发现!AI写作这样用,热点文章轻松超越同行90%!
做自媒体,写热点文章很重要。 热点自带流量,能很快吸引不少读者。 可很多自媒体新手很犯愁。 干货文还能勉强写出来,碰到热点文就不知咋办了。 为啥写热点文章这么难呢? 关键是得找个新颖角度切入。 要是只在网上反复复制粘贴那些…...

WPF常见容器全方位介绍
Windows Presentation Foundation (WPF) 是微软的一种用于构建Windows桌面应用程序的UI框架。WPF的布局系统基于容器,帮助开发者以灵活、响应的方式组织用户界面 (UI) 元素。本篇文章将详细介绍WPF中几种常见的容器,包括Grid、StackPanel、WrapPanel、Do…...

重置时把el-tree树节点选中状态取消
要重置 Element UI 的 el-tree 组件并取消所有节点的选中状态,可以通过以下几种方法: 使用 setCheckedKeys 方法: 如果你的树配置了 node-key 属性,可以使用 setCheckedKeys 方法来清空所有选中的节点。 this.$refs.tree.setCheck…...

服务器系统克隆技术
工作任务:克隆对象是Windows server2019 和2022的datacenter版本 条件:在已经完成安装的虚拟机上做克隆 图1-1 用两个服务器的母盘准备进行克隆 第一步:新建一个文件目录用于安放克隆好的服务器 图1-2 创建两个目录用于安放即将克隆好的服务…...

【Java】多线程 Start() 与 run() (简洁实操)
Java系列文章目录 补充内容 Windows通过SSH连接Linux 第一章 Linux基本命令的学习与Linux历史 文章目录 Java系列文章目录一、前言二、学习内容:三、问题描述start() 方法run() 方法 四、解决方案:4.1 重复调用 .run()4.2 重复调用 start()4.3 正常调用…...

基于微信小程序的购物系统【附源码、文档】
博主介绍:✌IT徐师兄、7年大厂程序员经历。全网粉丝15W、csdn博客专家、掘金/华为云//InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专栏推荐订阅👇dz…...

AI绘画:24最新Stable Diffusion 终极炼丹宝典:从入门到精通!
前言 我是咪咪酱,以浅显易懂的方式,与大家分享那些实实在在可行之宝藏。 历经耗时数十个小时,总算将这份Stable Diffusion的使用教程整理妥当。 从最初的安装与配置,细至界面功能的详解,再至实战案例的制作…...

线性可分支持向量机的原理推导【补充知识部分】拉格朗日函数 公式解析
本文是将文章《线性可分支持向量机的原理推导》中的公式单独拿出来做一个详细的解析,便于初学者更好的理解。在主文章中,有一个部分是关于补充拉格朗日对偶性的相关知识,此公式即为这部分内容。 公式 9-9 是关于拉格朗日函数 L ( x , α , β…...

csdn(最新交流群)
SEOI Chathttps://seoi.net/room/10122?kwe7cp45v此网站开放性较强,小心诈骗...

新手maven入门学习教程
MAVEN基础入门 提示:java新人的学习之路记录 学习内容: 提示:了解并会初步使用maven构建管理java项目 Maven 是一个非常流行的 Java 项目管理和构建工具。它通过提供一套标准的构建生命周期和一组预定义的目标来简化 Java 应用程序的构建过…...

React 中级阶段学习计划
React 中级阶段学习计划 目标 掌握状态管理和路由。能够调用API并处理异步数据。学会使用CSS-in-JS和CSS Modules进行样式处理。 学习内容 状态管理 React Context API Context API:用于在组件树中传递数据,避免多层props传递。示例:im…...

[产品管理-47]:产品市场调研 - 一级市场、二级市场、次级市场?
目录 一、产品销售环节的一级二级市场 1、一级市场 2、二级市场 3、一级市场与二级市场的互动关系 二、金融中的一级二级市场 1、一级市场(Primary Market)- 新股发行、定向发行 2、二级市场(Secondary Market)- 普通投资者…...

Linux零基础教程学习(黑马)
1.初识Linux 1.2远程连接Linux系统 图形化、命令行 对于操作系统的使用,有2种使用形式: 图形化页面使用操作系统 以命令的形式使用操作系统 不论是Windows还是Linux亦或是MacOS系统,都是支持这两种使用形式。 图形化:使用操作…...

一款零依赖、跨平台的流媒体协议处理工具,支持 RTSP、WebRTC、RTMP 等视频流协议的处理
大家好,今天给大家分享一款功能强大的流媒体协议处理工具go2rtc,支持多种协议和操作系统,具有零依赖、零配置、低延迟等特点。 项目介绍 go2rtc可以从各种来源获取流,包括 RTSP、WebRTC、HomeKit、FFmpeg、RTMP 等,并…...

PHP 正则验证A-Z且排除某字母
都已经找到这里来了,相信已经尝试很多办法了,那么我们直接上答案 关键正则:(?!.*[IO]) //验证5到6个大写字母且排除I和O if (preg_match(/^(?!.*[IO])[A-Z\d]{5,6}$/u, AAAAM)) {echo "匹配成功"; } else {echo "匹配失败…...

如何安全运行别人上传的Python代码?
写后端的同学,有时候需要在网站上实现一个功能,让用户上传或者编写自己的Python代码。后端再运行这些代码。 涉及到用户自己上传代码,我们第一个想到的问题,就是如何避免用户编写危险命令。如果用户的代码里面涉及到下面两行&…...

matlab相位图
% 清空工作空间和命令窗口 clear; clc; % 模拟生成时间t,位移y(t)和角位移theta(t) t linspace(0, 100, 1000); % 时间从0到100,包含1000个点 y 1e-5 * sin(2 * pi * 0.1 * t) .* exp(-0.01 * t); % 位移y(t) 振荡衰减 theta 1e-6 * cos(2 * pi * …...

C语言笔记(指针的进阶)
目录 1.字符指针 2.指针数组 3.数组指针 3.1.创建数组指针 3.2.&数组名和数组名 1.字符指针 int main() { char ch w;char* pc &ch;const char *p "abcdef";//常量字符串 产生的值就是首元素的地址//常量字符串不能被修改 因此需要加上一个…...
NodeJS连接MySQL 8.4报错:code: ‘ER_TABLEACCESS_DENIED_ERROR‘
NodeJS连接MySQL 8.4报错:code: ER_TABLEACCESS_DENIED_ERROR { code: ER_TABLEACCESS_DENIED_ERROR, errno: 1142, sqlMessage: "SELECT command denied to user 用户名localhost for table 表名", sqlState: 42000, index: 0, sql: SELECT …...

力扣66~70题
题66(简单): python代码: class Solution:def plusOne(self, digits: List[int]) -> List[int]:s_str.join([str(i) for i in digits])nstr(int(s_str)1)n_strlist(n)res[int(i) for i in n_str]return res题67(简…...

Axure重要元件三——中继器添加数据
亲爱的小伙伴,在您浏览之前,烦请关注一下,在此深表感谢! 本节课:中继器添加数据 课程内容:添加数据项、自动添加序号、自动添加数据汇总 应用场景:表单数据的添加 案例展示: 步骤…...

矩阵系统哪家好~矩阵短视频运营~怎么矩阵OEM
一、引言 在当今的数字化时代,矩阵系统在众多领域中发挥着至关重要的作用,如视频监控、信号切换、自动化控制等。然而,如何判断一个矩阵系统是否好用成为了许多用户面临的问题。本文将从多个方面探讨矩阵系统好用与否的判断标准,希…...

Axure树形菜单展开与折叠
亲爱的小伙伴,在您浏览之前,烦请关注一下,在此深表感谢! 课程主题:Axure树形菜单展开与折叠 主要内容:树形菜单制作——层级关系——隐藏与显示——值的变化——多层交互 应用场景:关系树、菜…...

开发一个微信小程序要多少钱?
在当今数字化时代,微信小程序成为众多企业和个人拓展业务、提供服务的热门选择。那么,开发一个微信小程序究竟需要多少钱呢? 开发成本主要取决于多个因素。首先是功能需求的复杂程度。如果只是一个简单的信息展示小程序,功能仅限…...

AnaTraf | TCP重传的工作原理与优化方法
目录 什么是TCP重传? TCP重传的常见触发原因 TCP重传对网络性能的影响 1. 高延迟与重传 2. 吞吐量的下降 如何优化和减少TCP重传 1. 优化网络设备配置 2. 优化网络链路 3. 网络带宽的合理规划 4. 部署CDN和缓存策略 结语 AnaTraf 网络性能监控系统NPM | …...

python从0快速上手(一)python环境搭建 windows macos linux
Python环境搭建超详细指南 Python是一种广泛使用的高级编程语言,它以其简洁的语法和强大的功能而受到开发者的喜爱。对于初学者来说,搭建一个合适的Python开发环境是开始Python之旅的第一步。本文将为你提供一个超级详细的Python环境搭建指南࿰…...

麒麟aarch64架构下安装compat-openssl10
问题描述: 麒麟aarch64架构下安装mysql8.0.40,报错nothing provides libcrypto.so.10()(64bit) needed by 原因: 你当前系统的 OpenSSL 版本与 MySQL 8.0.40 所需的库不匹配。MySQL 8.0.40 需要 libcrypto.so.10,而你的系统使用的是 OpenS…...

React远程组件
什么是远程组件? 远程组件指的是从远程服务器动态加载的组件,这些组件可以是React、Vue等框架的组件。 为什么需要远程组件 本质上就是为了解决复用问题,那引出新的问题有几种公共项目代码复用方式? Git仓库 将公共代码单独抽…...