SparrowRTOS系列:链表版本内核
前言
Sparrow RTOS是笔者之前写的一个极简性RTOS,初代版本只有400行,后面笔者又添加了消息队列、信号量、互斥锁三种IPC机制,使之成为一个较完整、堪用的内核,初代版本以简洁为主,使用数组和表作为任务挂载的抽象数据结构,对数表版本的Sparrow RTOS总结如下:
缺陷
由于数组和表的限制,该版本并不支持同优先级和时间片功能,设计互斥锁时也受到一定影响,而且最大只支持32个任务,有许多不便之处。
优点
使用数表存储任务,对任务的挂载以位操作和下标操作为主,内核简洁小巧,执行效率高,适用于任务较少、硬件资源少的情况。
链表版本内核的设计
使用链表作为任务挂载的数据结构,能够实现同优先级、时间片等功能,对任务对象的操作也更加灵活。
链表设计
任务链表由头部节点和任务节点两部分组成,头部会指向头节点和尾节点,头节点到尾节点之间会形成一个环路。
就绪列表设计
链表简化设计如下:
实际设计:
任务节点通过链表进行挂载,那么怎么找到任务对象的起始地址呢?
请读者想一想,任务对象的成员都是已知的,所以我们完全可以用链表节点的地址减去前面的成员的地址,就能得到任务对象的起始地址,然后再把起始地址类型转换为任务对象指针。
基于这个思想,其实我们是可以在面向对象的语言中修改私有属性的(如果这门语言支持指针这种直接操作内存的语法的话)。
不过一个个算还是太麻烦了,我们可以直接使用宏:
//get father struct address
//how to use it:struct parent *parent_ptr = container_of(child_ptr, struct parent, child)
#define container_of(ptr, type, member) \((type *)((char *)(ptr) - offsetof(type, member)))
这样就可以直接通过链表找到任务对象起始地址了。
相对于初步的Sparrow RTOS,链表版本的功能增加如下,增加了一个TimeSlice,也就是时间片功能。
void xTaskCreate( TaskFunction_t pxTaskCode,const uint16_t usStackDepth,void * const pvParameters,uint32_t uxPriority,TaskHandle_t * const self,uint8_t TimeSlice)
任务优先级设置
使用链表数组对应每个优先级,因此我们可以通过设置链表数组的大小来更改支持的优先级范围。不过由于支持同优先级和时间片,因此挂载的任务数量其实是不受限制的(除非内存不够)。
时间片
时间片是针对同优先级的说法,当最高优先级有多个任务时,每个任务会根据自身设置的时间片轮流享有CPU运行时间。
在时钟触发型RTOS中,一个时间片就是两次systick时钟中断之间的响应间隔,在Sparrow RTOS中,默认为1ms。
例如:
xTaskCreate( taskA,256,NULL,3,&tcbTask1,1);xTaskCreate( taskB,256,NULL,3,&tcbTask2,3);
对于taskA和taskB,当最高优先级为3时,这两个任务会轮流执行,不过taskA只会执行1个时间片,然后就会将CPU执行权交给taskB,taskB会执行三个时间片,然后再将CPU执行权交给taskA,如此反复循环(如果最高优先级一直是3)。
互斥锁设计
在Sparrow RTOS的数表版本中,互斥锁的优先级反转功能是设置优先级为阻塞任务中最大的那个优先级+1,但是这样会导致浪费优先级,对于可能发生阻塞的任务,我们要确保这些任务的优先级必须设置合理,不然会导致灾难的发生。
但是对于链表版本,由于支持同优先级,因此我们可以设置相同的优先级避免优先级反转现象的发生,而不会占用额外的优先级。
原子操作
由于临界区屏蔽中断的较为粗暴,所以对于简单的加减操作,可以使用内核提供的原子操作,例如:
atomic_add(a,v),表示*v + a
atomic_inc(v),表示*v自加
考虑下面的情况:
void taskA(){a++;
任务切换发生,另一个任务令a++;b = a;读取a,但是a的值是错误的
}void taskB(){a++;c = a; a的值是错误的
}
我们使用A和B两个线程对a进行递增,但是两个线程的递增可能是无效的,例如:
原子操作具有return版本,例如:
int a = atomic_inc_return(a,v);
其实原子操作不仅可以保证线程操作的原子性,也可以在多CPU条件下保证数据操作的原子性。
总结
以上就是对Sparrow RTOS链表版本内核的总结,整体来看,链表版本支持更多任务数量和功能,但是执行效率和简洁性不如数表版本,不过二者适用情景不同,根据实际情况选择即可。
笔者本人更喜欢数表版本,只使用了几百行程序就实现了RTOS的基本功能,简洁明了,同时也是一个良好的学习素材。笔者追求的程序风格一直都是模块化、高效、简洁明了,数表版本的内核是非常令笔者得意的,毕竟几千几万行的操作系统内核浩如烟海,几百行的可不多见。
对于学习Sparrow RTOS的读者来说,笔者推荐数表版本的内核,虽然代码量不多,但彻底搞懂并能更改代码可不容易。
结语
Sparrow RTOS将会持续维护更新,不断完善,其实笔者也是有为它添加设备树、驱动框架和网络协议栈这些功能的想法,不过这都是后话了,也许哪天会更新,也许一直没时间做这些,这都是不确定的。不过它的初衷就是一个学习用途的RTOS,而它也确实非常适合这一任务。
最后,笔者真诚希望读者都能在Sparrow RTOS的教程中收获对操作系统的思考与领悟,操作系统的学习之路道阻且长,在海滩拾贝的过程中,希望读者也能收获属于自己的快乐。
以上,与君共勉。
项目地址:skaiui2/SKRTOS_sparrow: Lightweight rtos inspired by SKRTOS
相关文章:
SparrowRTOS系列:链表版本内核
前言 Sparrow RTOS是笔者之前写的一个极简性RTOS,初代版本只有400行,后面笔者又添加了消息队列、信号量、互斥锁三种IPC机制,使之成为一个较完整、堪用的内核,初代版本以简洁为主,使用数组和表作为任务挂载的抽象数据…...
Elasticsearch—索引库操作(增删查改)
Elasticsearch中Index就相当于MySQL中的数据库表 Mapping映射就类似表的结构。 因此我们想要向Elasticsearch中存储数据,必须先创建Index和Mapping 1. Mapping映射属性 Mapping是对索引库中文档的约束,常见的Mapping属性包括: type:字段数据类…...
RabbitMQ高级篇
目录 确保发送者的可靠 为什么需要确保发送者的可靠性 RabbitMQ 的发送者重连机制配置 springAMQP实现发送者确认 MQ的可靠性 为什么需要实现MQ的可靠性? 数据持久化 Lazy Queue 核心思想 总结RabbitMQ 如何保证消息的可靠性 持久化 Lazy Queue 消息…...
R4-LSTM学习笔记
🍨 本文为🔗365天深度学习训练营 中的学习记录博客🍖 原作者:K同学啊 LSTM-火灾温度预测 导入数据数据可视化设置X、y构建模型调用模型个人总结LSTM 的基本结构细胞状态(Cell State)LSTM 的优点 导入数据 i…...
Unity搭配VS Code使用
1.Unity编辑器中设置External Tools为VS Code Edit->Preferces->External Tools->Visual Studio Code 2.VS Code安装Unity插件 快捷键“CtrlShiftX”输入“Unity”点击“Install” 3.下载安装.Net 下载 .NET 8.0 (Linux、macOS 和 Windows) 下载完成后安装.Net输…...
Go Ebiten小游戏开发:井字棋
今天我将分享如何使用 Go 语言和 Ebiten 游戏库开发一个简单的井字棋游戏。Ebiten 是一个轻量级的 2D 游戏库,非常适合用来开发小型游戏。通过这个项目,我们可以学习到如何使用 Ebiten 处理输入、渲染图形以及管理游戏状态。 项目概述 井字棋是一个经典…...
嵌入式系统中的 OpenCV 与 OpenGLES 协同应用
🎬 秋野酱:《个人主页》 🔥 个人专栏:《Java专栏》《Python专栏》 ⛺️心若有所向往,何惧道阻且长 文章目录 一、OpenCV 在嵌入式中的基石地位二、OpenGLES 为嵌入式图形渲染赋能三、二者协同的精妙之处四、面临的挑战与应对策略 在嵌入式开…...
秒懂虚拟化(二):服务器虚拟化、操作系统虚拟化、服务虚拟化全解析,通俗解读版
秒懂虚拟化(一):从概念到网络、存储虚拟化全解析,通俗解读版-CSDN博客这篇文章学习了虚拟化的概念、网络虚拟化和存储虚拟化,本节将继续学习服务器虚拟化、操作系统虚拟化、服务虚拟化。 1、服务器虚拟化 服务器虚拟…...
Java定时任务
在 Java 中,定时任务通常用于在特定时间或间隔执行某个操作。Java 提供了多种方式来实现定时任务,包括使用 Timer 类、ScheduledExecutorService 和 Spring 框架中的定时任务功能。下面将介绍这些常见的方法。 1. 使用 Timer 类 Timer 类可以用来安排任…...
springCloud特色知识记录(基于黑马教程2024年)
目录 Nacos 简介 Nacos 的特点 Nacos 的使用步骤可以查看黑马教程文档:day03-微…...
Linux---shell脚本练习
要求: 1、shell 脚本写出检测 /tmp/size.log 文件如果存在显示它的内容,不存在则创建一个文件将创建时间写入。 2、写一个 shel1 脚本,实现批量添加 20个用户,用户名为user01-20,密码为user 后面跟5个随机字符。 3、编写个shel 脚本将/usr/local 日录下…...
ClickHouse-CPU、内存参数设置
常见配置 1. CPU资源 1、clickhouse服务端的配置在config.xml文件中 config.xml文件是服务端的配置,在config.xml文件中指向users.xml文件,相关的配置信息实际是在users.xml文件中的。大部分的配置信息在users.xml文件中,如果在users.xml文…...
浅谈云计算02 | 云计算模式的演进
云计算计算模式的演进 一、云计算计算模式的起源追溯1.2 个人计算机与桌面计算 二、云计算计算模式的发展阶段2.1 效用计算的出现2.2 客户机/服务器模式2.3 集群计算2.4 服务计算2.5 分布式计算2.6 网格计算 三、云计算计算模式的成熟与多元化3.1 主流云计算服务模式的确立3.1.…...
设置模块一级菜单添加遥控器功能
文章目录 问题点问题分析资源和源码分析解决方案源码分析找到对应的Activitymenifest 分析SettingsHomepageActivity 分析 问题点 MTK Android12/13 系统设置一级界面,蓝牙遥控器无法上下滑动页面。 备注:自己对设置整个模块系统其实并不熟悉ÿ…...
Blazor中Syncfusion Word组件使用方法
Blazor中Syncfusion Word组件用于在Blazor应用程序中创建、编辑、查看和打印 Word(DOC、DOCX 和 RTF)文档。 主要功能: 从头开始创建文档。打开和编辑 Word(DOC、DOCX)、RTF 和 SFDT(Syncfusion 文档文本…...
HTB:Driver[WriteUP]
目录 连接至HTB服务器并启动靶机 信息收集 使用rustscan对靶机TCP端口进行开放扫描 将靶机TCP开放端口号提取并保存 使用nmap对靶机TCP开放端口进行脚本、服务扫描 使用nmap对靶机TCP开放端口进行漏洞、系统扫描 使用nmap对靶机常用UDP端口进行开放扫描 使用smbclient尝…...
微信小程序-Docker+Nginx环境配置业务域名验证文件
在实际开发或运维工作中,我们时常需要在 Nginx 部署的服务器上提供一个特定的静态文件,用于域名验证或第三方平台验证。若此时使用 Docker 容器部署了 Nginx,就需要将该验证文件正确地映射(挂载)到容器中,并…...
55_OpenResty开发入门
Nginx编程需要用到Lua语言,因此我们必须先学习Lua的基本语法。Nginx本身也是C语言开发,因此也允许基于Lua做拓展。多级缓存的实现离不开Nginx编程,而Nginx编程又离不开OpenResty。 1.OpenResty概述 OpenResty是一款基于NGINX和LuaJIT的Web平台。通过Lua扩展NGINX实现的可伸…...
Windows安装Jenkins——及修改主目录、配置简体中文、修改插件源
一、简介 Jenkinshttps://www.jenkins.io/zh/ Jenkins是开源CI&CD软件领导者, 提供超过1000个插件来支持构建、部署、自动化, 满足任何项目的需要。 二、Windows安装配置Jenkins2.479 2.1、J...
大数据环境搭建进度
1.使用虚拟机的系统:centos7.xLinux 2.资源不足,使用云服务器: 1. 3.使用远程登录进行操作 用xshell 4.任务 1.虚拟机装好 2.设置IP地址 3.可以联网 4.设置远程登录访问 5.创建module和software目录,修改两…...
React Native 开发环境搭建(全平台详解)
React Native 开发环境搭建(全平台详解) 在开始使用 React Native 开发移动应用之前,正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南,涵盖 macOS 和 Windows 平台的配置步骤,如何在 Android 和 iOS…...
Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...
苍穹外卖--缓存菜品
1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得,如果用户端访问量比较大,数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据,减少数据库查询操作。 缓存逻辑分析: ①每个分类下的菜品保持一份缓存数据…...
JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作
一、上下文切换 即使单核CPU也可以进行多线程执行代码,CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短,所以CPU会不断地切换线程执行,从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...
全志A40i android7.1 调试信息打印串口由uart0改为uart3
一,概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本:2014.07; Kernel版本:Linux-3.10; 二,Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01),并让boo…...
pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)
目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关࿰…...
通过 Ansible 在 Windows 2022 上安装 IIS Web 服务器
拓扑结构 这是一个用于通过 Ansible 部署 IIS Web 服务器的实验室拓扑。 前提条件: 在被管理的节点上安装WinRm 准备一张自签名的证书 开放防火墙入站tcp 5985 5986端口 准备自签名证书 PS C:\Users\azureuser> $cert New-SelfSignedCertificate -DnsName &…...
LOOI机器人的技术实现解析:从手势识别到边缘检测
LOOI机器人作为一款创新的AI硬件产品,通过将智能手机转变为具有情感交互能力的桌面机器人,展示了前沿AI技术与传统硬件设计的完美结合。作为AI与玩具领域的专家,我将全面解析LOOI的技术实现架构,特别是其手势识别、物体识别和环境…...
以太网PHY布局布线指南
1. 简介 对于以太网布局布线遵循以下准则很重要,因为这将有助于减少信号发射,最大程度地减少噪声,确保器件作用,最大程度地减少泄漏并提高信号质量。 2. PHY设计准则 2.1 DRC错误检查 首先检查DRC规则是否设置正确,然…...
使用homeassistant 插件将tasmota 接入到米家
我写一个一个 将本地tasmoat的的设备同通过ha集成到小爱同学的功能,利用了巴法接入小爱的功能,将本地mqtt转发给巴法以实现小爱控制的功能,前提条件。1需要tasmota 设备, 2.在本地搭建了mqtt服务可, 3.搭建了ha 4.在h…...
