0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

RT-Thread 遇上 Rust:安全内核 RusT-Thread 的诞生

RT-Thread官方账号 ? 2025-08-02 11:03 ? 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

大家好,我们是中国科学技术大学操作系统原理与设计(H)课oooooS小组。这个项目是我们的课程大作业:参考RT-Thread架构,使用Rust搭建一个原生的嵌入式操作系统内核。初识Rust是因为xk老师的推荐,很快我们就被其极高的安全特性,强大的包管理系统和编译器以及丰富的社区支持所折服。然后我们在调研时注意到了RT-Thread。它有着经典的操作系统架构,却又在各模块的设计上充满着巧思,最重要的是,它的社区支持和文档支持也非常丰富,这给我们的工作带来了非常多的便利。所以,在课程结束后,我们也想做些工作来反哺开源社区,这才有了这篇文章的诞生。囿于本组组员的水平,以下内容仅供参考,当然也欢迎读者有任何疑问的话与我们联系。

项目地址:https://github.com/OSH-2025/oooooS

小组全体成员: @Piteright , @明日桐奈,@故俗,@LISTOI,@老葵泽

物联网嵌入式系统领域,对功能安全与高可靠性的追求已成为行业共识,尤其是在资源受限的微控制器MCU)应用中。传统上,这类系统大量依赖C语言开发的实时操作系统(RTOS),通过任务(线程)作为并发与隔离的基本单元。然而,C语言固有的内存安全缺陷,如缓冲区溢出、悬垂指针等,使得在协作式多任务环境下,任何一个组件的微小失误都可能导致整个系统的崩溃,这在工业控制、医疗设备、汽车电子等关键领域是不可接受的。开发者不得不在功能实现与系统稳定性之间艰难权衡,投入大量精力进行防御性编程和冗长的测试。

RusT-Thread正是在这样的背景下诞生的。作为一款专为资源受限嵌入式平台设计的开源实时操作系统,RusT-Thread 以业界成熟的 RT-Thread 内核理念为蓝本,创新性地采用 Rust语言进行全面重构。它旨在从根本上解决传统 RTOS 的安全痛点,利用 Rust 语言强大的静态分析能力,包括所有权系统、借用检查和类型安全,将大量潜在的内存与并发错误在编译阶段彻底消除。通过这种方式,RusT-Thread 致力于在不牺牲性能的前提下,提供一个轻量级、高安全性的并发执行环境。

本文将从项目特色、架构设计、核心实现机制、性能验证等多个维度,详细阐述 RT-Thread 的设计理念与实现方式,展示其如何将 Rust 的现代化语言优势与实时操作系统的经典思想相结合,为嵌入式开发者提供一个更安全、更高效的开发新选择。


目录


简介


项目特色


架构设计


分模块介绍


性能与验证


优缺点


总结与展望

1

简介


RusT-Thread是一款基于 RT-Thread 理念,采用 Rust 语言打造的轻量级实时操作系统内核,已在ARM Cortex-M4上成功实现,并有望拓展至更多芯片平台。

在线程调度上,它支持多线程创建、调度及优先级管理,提供多种调度算法,如优先级、优先级 + RR 等。同时,在内存分配上支持伙伴系统、小内存分配器等多种内存分配方式,满足动态内存分配需求。此外,还实现了高精度定时器,支持单次和周期定时功能,并具备完整的异常和中断处理机制。

RusT-Thread 的 Rust 实现保障内存安全,模块化设计便于扩展和移植,支持资源受限的嵌入式系统,为开发者提供了安全、高效、精简的 Rust 原生实时操作系统选择。


2

项目特色


本项目是一个完全由Rust构建的操作系统内核。不同于本课程其他小组和前辈们的工作,我们放弃了C和Rust混合编译改写操作系统内核的开发路径,而是选择从底层开始就用 Rust开发,这种彻底的重构能让我们更好地利用Rust拥有的现代化语言特性,组织起结构更加清晰功能实现更加简练的代码。同时,我们还避免了混合编译过程中的各种操作性问题和潜在的安全性风险。

本项目的架构参考RT-Thread nano内核实现,在实现功能模块时我们保留了大部分RT-Thread内核的接口,确保熟悉RT-Thread内核的开发者能低成本快速上手我们的内核。RT-Thread的成功很难离开其众多贡献者带来的丰富软件包移植,我们希望我们的内核也能为 RT-Thread社区中的Rust开发者提供一个底层平台,可以原生的用Rust实现各种组件,丰富这个操作系统的功能。


3

架构概述


44f96f94-6f4d-11f0-9080-92fbcf53809c.jpg

RusT-Thread结构

当我们着手设计 RusT-Thread 架构时,我们的目标并不仅仅是复刻 RT-Thread,而是要用 Rust 的思想去重塑它。为此,我们将以下几个关键原则融入了项目里:

安全性 :借助 Rust 的所有权系统与借用检查机制,从编译阶段就彻底消除内存安全隐患。同时,通过其严格的并发模型有效防止数据竞争,能够有效提升系统的并发安全性

可扩展性 :我们将整个系统设计为高度模块化。这种架构使得无论是添加新的设备驱动、文件系统,还是集成复杂的网络协议栈,都变得直观而高效,为未来的功能拓展留出了充足的空间

性能:充分利用 Rust 的零成本抽象特性,在确保系统安全性的基础上,对调度算法和内存管理机制进行深度优化,从而全面提升系统的整体性能表现

易移植性:我们采用分层设计策略并构建清晰的硬件抽象层,简化了系统对不同芯片架构的适配过程。目前,该系统已成功支持 ARM Cortex-M4 芯片架构,未来也许会逐步扩展对更多类型芯片的支持范围


4

分模块介绍


1 内核服务层

内核服务层作为 RusT-Thread 操作系统的核心基础,是连接硬件底层与上层应用的关键桥梁,其核心功能及在 Rust 中的实现方案如下:

错误处理机制:采用 Rust 的OptionResult枚举类型替代传统错误码,通过模式匹配清晰表达函数执行结果。在编译期对错误处理逻辑进行严格检查,避免因错误处理不当引发的问题,确保系统稳定运行。

内存操作函数:利用 Rust 标准库中的 Core::alloc模块,结合自定义的内存分配策略和数据结构,实现高效灵活的内存分配与回收机制,优化内存使用效率,确保操作的正确性和安全性。

字符串操作函数:借助 Rust 内置的Stringstr类型及其操作方法,实现功能强大且安全高效的字符串处理功能,有效防止缓冲区溢出等问题,满足系统对文本处理的需求。

格式化输出功能:结合cortex_m_semihosting工具库和 Rust 的格式化字符串宏(format!println!等),实现数据格式化输出功能。在QEMU模拟器环境下,通过半宿主功能将输出数据发送至宿主机控制台,支持多种数据类型和输出格式,满足调试和信息展示的需求。

调试和断言功能:借助 Rust 的DebugDisplay特性以及assert!debug_assert!等宏,实现完善的调试和断言功能。为自定义数据类型实现相关特质,以便在调试输出时展示详细信息;通过断言条件检查及时暴露问题,提高开发效率。

链表实现:利用 Rust 的Vec等标准容器类型,结合手动指针操作和数据结构管理逻辑,构建高效的链表结构。通过存储节点指针模拟链接关系,实现节点的动态操作,同时借助所有权系统和借用检查机制确保操作的安全性和正确性。

我们单独添加了 Cell 模块,以更好地适配 Rust 的语言特性。Cell 模块实现了一个中断安全的共享数据容器RTIntrFreeCell,这是 RT-Thread 实时操作系统中的核心内核服务组件之一。其核心目的就是在多线程和中断环境下提供安全的共享数据访问机制,通过自动禁用和启用中断来防止数据竞争,具体体现在以下三个方面:

1. 中断安全性:

在访问共享数据时自动调用rt_hw_interrupt_disable()禁用中断

访问结束后自动调用rt_hw_interrupt_enable()恢复中断

确保临界区代码能够原子性地执行,避免数据不一致的问题

2. RAII 资源管理:

使用RTIntrRefMut作为智能指针,利用 Rust 的 Drop 特质实现自动资源释放

RTIntrRefMut超出作用域时,自动恢复中断级别,降低了手动管理资源的风险

3. 灵活的访问方式:

提供exclusive_access()方法获取独占访问权限

提供exclusive_session()方法在闭包中执行临界区代码

提供as_ptr()as_mut_ptr()方法获取原始指针,方便底层操作

提供field_ptr()field_mut_ptr()方法获取结构体字段的原始指针,增强灵活性

在 RusT-Thread 内核中,我们使用这个核心模块来保护那些需要同时被中断服务程序和普通线程访问的关键数据,比如线程控制块(TCB)、调度器状态、定时器列表以及内存管理的内部数据。RTIntrFreeCell的作用就是提供一个“中断锁”,确保在任何时候数据访问都是安全的,这对于保证高并发下系统的数据一致性和整体稳定性至关重要。


2 硬件抽象层

硬件抽象层(hardware)是 RusT-Thread 操作系统在 Cortex-M4 架构下的底层硬件支持模 块,主要负责 CPU 端口、上下文切换、异常处理和中断管理等功能,为上层系统提供与硬件紧密相关的基础服务。

硬件抽象层是操作系统的核心组成部分,通过这些模块,RusT-Thread 能够实现高效、可靠的硬件资源管理和任务调度,为上层应用提供稳定的运行环境。

模块内容如下:

hardware├── context.rs # 线程上下文切换,使用内联汇编实现线程上下文保存与恢复├── cpuport.rs # CPU 接口-Cortex-M4,定义了异常栈帧、栈帧、CPU关机、CPU 重启├── exception.rs # 异常处理相关函数├── irq.rs # 中断管理模块,提供了中断嵌套计数、钩子设置、使能/禁用中断等功能└── mod.rs # 统合上述模块,提供对外接口

上下文切换模块 (context.rs)

负责线程上下文的切换机制,主要功能包括:

线程上下文的保存与恢复

PendSV 中断处理(实际执行上下文切换)

提供rt_hw_context_switchrt_hw_context_switch_interruptrt_hw_context_switch_to等上下文切换处理函数

实现线程间的高效切换,是多线程调度的核心机制

CPU 端口模块 (cpuport.rs)

提供与 CPU 硬件直接相关的底层支持:

定义异常栈帧ExceptionStackFrame和栈帧StackFrame结构

实现线程栈初始化函数rt_hw_stack_init

提供 CPU 关机rt_hw_cpu_shutdown和重启rt_hw_cpu_reset等功能

可选的 FPU 支持(浮点运算单元)

中断管理模块 (irq.rs)

实现中断处理相关的功能:

中断嵌套计数管理

提供中断使能/禁用函数rt_hw_interrupt_disable/enable

中断进入/退出处理rt_interrupt_enter/leave

支持中断钩子函数设置(通过特性开关控制

获取中断嵌套层数rt_interrupt_get_nest

异常处理模块 (exception.rs)

负责处理系统运行中的各种异常:

提供硬件错误处理(HardFault、MemManage、BusFault、UsageFault)

异常信息收集与输出

支持异常钩子机制rt_hw_exception_install

详细的故障跟踪与诊断功能


3进程调度层

作为 RusT-Thread 操作系统的核心,进程调度层负责管理和调度所有线程,确保它们能够高效、公平地共享处理器资源,实现并发执行,核心职责如下:

任务调度:依据预设调度策略,决定处理器执行权的分配,保障高优先级任务的及时响 应,同时兼顾任务的公平执行。支持多种调度算法,具备灵活适应不同应用场景和实时性要求的能力

调度算法选择 :提供优先级调度算法(如优先级 + 时间片轮转)和多级反馈队列调度算法等,用户可根据实际需求灵活选择调度算法,满足不同任务对实时性和资源分配的需求

线程 API 接口 :为用户提供了一系列丰富的接口,使用户能够更加便捷地对线程状态进行调整和控制,例如创建、删除、挂起、恢复线程等操作,同时提供了获取和设置线程属性的接口,方便用户根据实际需求对线程进行精细化管理

45091624-6f4d-11f0-9080-92fbcf53809c.jpg

调度策略抽象 :通过定义 SchedulingPolicy特质,将多种调度算法封装和抽象。以优先级调度算法为例,实现了相应的结构体,包含线程优先级队列管理和时间片分配与轮转机制;对于多级反馈队列调度算法,设计了多级队列数据结构,实现了任务根据执行时间动态调整队列级别的逻辑。基于特质的抽象方式使调度策略切换灵活,用户在初始化时指定调度策略后,调度器即可根据具体实现执行调度操作

/// 调度策略 traitpub traitSchedulingPolicy:Send+Sync{ /// 选择下一个要运行的线程 /// /// # 参数 /// * `current_thread` - 当前运行的线程 /// /// # 返回值 /// * `Option<(Arc, bool)>` - (选中的线程, 是否需要将原线程重新插入就绪队列) fn select_next_thread( &self, current_thread:&Option>, )->Option<(Arc, bool)>; /// 获取策略名称 fn get_policy_name(&self) ->&'staticstr;}

调度算法优化 :引入位图 + FFS(Find First Set)算法提升调度效率。位图标识各优先级队列的线程就绪状态,通过 FFS 算法快速定位最高优先级队列中的首个就绪线程。FFS 算法借助预计算查找表,将复杂位运算转化为简单数组访问,实现 O(1) 时间复杂度的最高优先级线程查找,显著提升调度器响应速度和实时性能,确保系统及时响应高优先级任务

#[cfg(feature = "tiny_ffs")]const__LOWEST_BIT_BITMAP: [u8;37] = [ 0,1,2,27,3,24,28,32,4,17,25,31,29,12,32,14, 5,8,18,32,26,23,32,16,30,11,13,7,32,22,15,10, 6,21,9,20,19];
#[cfg(feature = "tiny_ffs")]pubfn__rt_ffs(value: u32) ->u8{ ifvalue ==0{ return0; } __LOWEST_BIT_BITMAP[((value & (value -1) ^ value) %37)asusize]}

该算法利用预计算查找表和数学运算避免复杂位运算循环,实现了快速最低有效位查找。它专为嵌入式环境优化,在资源受限设备上也能快速执行,满足实时系统低延迟要求。能快速确定线程就绪队列中最高优先级线程,确保调度器及时响应高优先级任务,提升系统实时性和性能。

多级反馈队列调度实现 :在多级反馈队列调度算法中,引入老化机制,使长期未被调度的线程逐渐升高优先级,防止低优先级线程饥饿,增强调度算法公平性和适应性。实现过程中,借助 Rust 语言零成本抽象特性,优化代码实现,提升系统稳定性和可维护性。


4 内存管理层

在 RusT-Thread 中,我们实现了原本 RT-Thread 中的小内存分配器,同时并支持了库实现的buddy_system allocatorgood_memory allocator,可供用户在实际场景中自由选择,下面将对小内存分配器作具体分析:

RusT-Thread 中的小内存分配器主要体现在如下几个文件中:

small_mem_impl.rs:核心算法实现

small_mem_allocator.rs、allocator.rs:分配器接口与适配

object.rs、safelist.rs:辅助对象和安全链表

oom.rs:内存溢出处理

451df3be-6f4d-11f0-9080-92fbcf53809c.jpg

表示内存块的结构体:

///RTSmallMemItem 结构体表示一个小内存块的基本信息,主要用于管理内存池中的单个内存块#[repr(c)]pub structRTSmallMemItem { ///内存池指针 pub pool ptr: usize, #[cfg(target_pointer_width="64")]// 条件编译,64位系统生效 pub resv:u32,//保留字段,用于对齐,64位系统下使用 ///下一个空闲块的指针 pub next: usize, ///前一个空闲块的指针 pub prev: usize, #[cfg(feature ="mem_trace")]//条件编译,内存跟踪生效 #[cfg(target pointer_width="64")]//条件编译,64位系统生效 pub thread:[u8;8],//线程ID,64位系统下使用 #[cfg(feature="mem_trace")]//条件编译,内存跟踪生效 #[cfg(target pointer_width ="32")]//条件编译,32位系统生效 pub thread:[u8;4],//线程ID,32位系统下使用}

小内存分配算法的原理是通过维护一块连续的内存池,将其划分为带有头部信息的内存块,并用链表管理空闲和已用块。分配时遍历空闲链表,找到足够大的块后分割并标记为已用;释放时将块标记为空闲,并尝试与相邻空闲块合并以减少碎片。整个过程包含边界检查和中断保护,确保分配、释放的安全性和原子性。

除了实现基本的小内存算法外,我们还有如下亮点:

边界检查与安全性提升

C 代码主要依赖 RT_ASSERT 等宏进行运行时断言,且大量裸指针操作,容易出现悬垂指针、越界、重复释放等问题,这些断言如果被关闭,代码安全性大幅下降

debug_assert!((memasusize) >= ((*small_mem).heap_ptrasusize)); debugassert!((memasusize) < ((*small_mem).heap_end?as?usize));? debug?assert!(mem?is?used(mem));if?m.is_null()||size ==?0?{? ? return?ptr::null mut();? }

Rust 利用类型系统和所有权机制,天然防止了大部分内存安全问题,同时 rt_smem_free、rt_smem_alloc 等函数在操作前都做了空指针和边界检查

Rust 的 debug_assert! 只在 debug 模式下生效,release 下可关闭,但类型系统和生命周期机制依然提供了额外的安全保障

许多辅助函数(如 mem_is_used、mem_pool 等)都用 inline 和类型安全的方式实现,减少了手动错误

中断保护

C 语言通过rt_hw_interrupt_disable/rt_hw_interrupt_enable 手动保护关键区,防止并发破坏堆结构

rt_base_t_level =rt_hw_interrupt_disable(); // ...关键区. rt_hw_interrupt_enable(level);

Rust 同样调用rt_hw_interrupt_disable/rt_hw_interrupt_enable,但更易于用 RAII(资源自动释放)等机制进行封装,减少人为失误

letlevel =rt_hw_interrupt_disable();//...关键区 ... rt_hw_interrupt_enable(level);

并且 Rust 代码结构更清晰,便于后续用 RAII 或作用域自动恢复中断,提升健壮性


5 线程通信

进程间通信(IPC)是多任务操作系统中各个任务之间进行数据交换和协同工作的重要手段。我们的 RusT - Thread 提供了信号量机制,而消息队列、邮箱等作为拓展,我们尚未支持。

信号量工作示意图如下图所示,每个信号量对象都有一个信号量值和一个线程等待队列,通过信号量的值是否为零,决定线程是否可以访问临界区的资源,当信号量实例数目为零时,再申请该信号量的线程就会被挂起在该信号量的等待队列上,等待可用的资源。

453327d4-6f4d-11f0-9080-92fbcf53809c.jpg

在 RT-Thread 中,信号量相关操作有以下函数——创建、删除、获取、释放,我们实现的思路和 C 类似,先实现 ipc 的基础操作,如_ipc_list_suspend挂起线程,_ipc_list_resume唤醒线程等等,然后,通过信号量的值,选择不同的操作,实现信号量的相关操作即可。

4548104a-6f4d-11f0-9080-92fbcf53809c.jpg


6 时钟控制层

时钟节拍的产生

时钟节拍由配置为中断触发模式的硬件定时器产生,当中断到来时,将调用一次rt_tick_increase()函数,通知操作系统已经过去一个系统时钟;不同硬件定时器中断实现都不同,Rust_Thread 的中断函数是在 QEMU 模拟器上的 stm32 系列单片机上实现的,具体的,程序中将使用#[exception]一个中断处理函数SysTick(),在其中调用rt_tick_increase()函数。

在 Rust-Thread系统中,使用常数 RT_TICK_PER_SECOND 控制时钟周期长度。本系统中默认主频是 16MHZ,是通过 QEMU 模拟芯片内部高速振荡器实现的,默认 RT_TICK_PER_SECOND=1000,即一个时钟周期 16000 个硬件周期。

时钟中断的管理

时钟中断管理核心函数rt_tick_increase()主要完成以下工作:

将全局变量RT_TICK 自增,这个变量记录了系统从初始化到当前经过了多少个时钟周期,叫做系统时间。

检查当前线程的时间片是否到期,若到期,则触发线程调度

检查是否有定时器到期,如果有,触发定时器超时函数

时钟管理中还包括系统时间的读取和设定函数,毫秒数和时钟周期数的转换函数等功能函数。

定时器的管理

RT-Thread 的定时器由定时器控制块RtTimer控制,定时器控制块全部在运行时动态分配内存并按照超时时间升序挂载在动态数组TIMERS中。定时器的管理主要包括定时器的创建、激活、修改、超时与停止。

创建:使用new方法创建,体现了面向对象的思想

激活:计算超时时刻,通过二分查找插入TIMERS数组,保证有序性

修改:使用enum封装所有修改操作(如周期、定时值),符合 Rust 风格且易于扩展。修改在下次激活时生效

超时:通过二分查找高效定位到期的定时器,执行回调。周期性定时器会自动重新激活,单次定时器则被移除

停止:TIMERS数组中移除并回收定时器


5

性能与验证


1 内存性能测试

原生的 RT-Thread 官方并没有给出一些具体的有关内存性能的数据,所以这里我们参照标准的 std 库来比较分析 RusT-Thread 的性能。

我们在 Linux(x86_64)平台下,使用 Rust 重新实现了 RusT-Thread 的完全相同的内存管理模块,并对其进行了适当的封装,并使其接口与原系统保持一致。这样,我们就可以在支持 std 库和Criterion基准测试框架的环境下,对内存分配、释放等核心操作进行高效、可重复的性能测试,并与 Rust 标准库分配器进行公平对比。

测试代码使用 Criterion 框架实现,测试内容包括小块分配、混合分配、碎片处理、内存利用率等多种典型场景

这种方法虽然不能完全反映嵌入式平台的绝对性能,但可以有效比较不同分配算法的相对性能,为实际部署和优化提供有价值的参考

具体测试结果如下:

4559248e-6f4d-11f0-9080-92fbcf53809c.jpg

该图展示了 RusT-Thread 与标准分配器在进行小块内存分配和混合内存分配时的性能表现:

Small Allocations 中,RusT-Thread 平均耗时约为 24.6?s,明显优于std的 77.7?s,表明 RusT-Thread 在频繁的小对象分配中具有更低的管理开销

Mixed Allocations 中,标准分配器表现优异,耗时仅约 5.7?s,而 RusT-Thread 则为 31.4?s,可能是由于 RusT-Thread 对变长内存块的处理不如标准库灵活高效

RusT-Thread 在固定小块内存操作中具有优势,但在面对内存尺寸变化复杂的情况时性能下降。不过这同时也崭展现出不同应用场景中,RusT-Thread 中小内存分配算法的性能更加稳定。


45681372-6f4d-11f0-9080-92fbcf53809c.jpg

该图展示了在逐步增加内存块大小的条件下,RusT-Thread 和标准分配器的单次分配耗时变化趋势:

RusT-Thread 的分配时间基本稳定在 7~8ns 范围内,说明其设计对小中等大小块分配进行了优化处理,性能几乎不受块大小影响

标准分配器的耗时随着块大小增加而变化更为剧烈,例如从 16B 的约 24ns 上升到 2048B时超过 47ns,说明其可能使用了更复杂的分配策略或存在内存对齐开销

可见,RusT-Thread 分配器的响应速度更稳定,适用于内存块尺寸变化不大的嵌入式任务场景。


457b2d68-6f4d-11f0-9080-92fbcf53809c.jpg

本图对比了在进行批量内存分配(10、100、1000 次)时,两种分配器的平均耗时:

RusT-Thread 在 10~100 次批量分配中仅需 17?s 左右,而标准分配器耗时逐步上升到 60?s 以上

差距在批量操作中进一步放大,表明 RusT-Thread 的批处理性能更优,内部结构对频繁申请释放有较强的适应性

可以看出,RusT-Thread 分配器在多次重复分配的密集型任务中更具优势,特别适用于任务频繁上下文切换或数据缓冲场景。


458795f8-6f4d-11f0-9080-92fbcf53809c.jpg

该图展示了常见四种内存重分配路径(如 64→128, 128→64, 64→256, 256→64)下的耗时比较:

所有场景中 RusT-Thread 的耗时都远低于标准分配器,例如 128→64 仅约 12.95ns,而标准库约 89.6ns

表明 RusT-Thread 分配器可能采用就地扩展或快速搬迁机制,避免了额外的复制和元信息更新开销

所以,RusT-Thread 对 reallocation 操作进行了优化,在需要动态改变内存块大小的场景中表现更加出色,这使得对于真实环境中的复杂情况的处理会更加优秀。


2 模块验证测试

测试部分代码结构如下:

RusT-thread/src/test├── README.md├── comprehensive_example.rs├── example.rs├── example_mfq.rs├── integration_test.rs├── mod.rs├── performance_test.rs├── switch_time_test.rs├── test_all.rs├── test_cell.rs├── test_excp.rs├── test_interupt.rs├── test_ipc.rs├── test_mem.rs├── test_scheduler.rs├── test_small_mem.rs├── test_thread.rs└── test_timer.rs


3 单元测试

我们为各个模块编写了详细的单元测试用例,对模块的功能进行充分验证。例如,对线程管理模块,测试了线程的创建、启动、挂起、恢复、删除等基本操作,以及不同调度策略下的线程切换和优先级管理;对内存管理模块,测试了内存的分配、释放、重分配等操作以及对标准 alloc 的容器支持;对定时器模块,测试了定时器的创建、启动、停止、重启等操作,以及定时器回调函数的执行等


4 集成测试

在模块间集成测试中,我们重点关注各模块协作及系统整体功能正确性,设计了以下典型测试场景:

并发性测试

并发线程创建:多线程同时创建 RT-Thread 线程,验证线程管理安全性

优先级调度验证:创建不同优先级线程并记录执行顺序,确保调度器优先级语义正确

内存碎片化测试:模拟复杂内存分配释放场景,验证内存管理器健壮性

压力测试

大规模线程创建:创建 100 个线程同时运行,测试系统高负载稳定性

内存分配压力测试:进行 1000 次随机大小内存分配释放,验证内存管理器性能

定时器密集测试:创建 50 个定时器同时运行,测试时钟系统处理能力

边界条件和错误处理

边界值测试:测试最小 / 最大优先级、最小内存分配、零大小分配等边界情况

错误场景模拟:测试重复启动线程、重复挂起线程、无效线程 ID 等异常处理

资源耗尽测试:模拟内存不足等资源耗尽场景,验证系统错误处理机制

系统稳定性测试

长时间运行测试:验证系统长期稳定性


5 性能基准测试

为验证 RusT-Thread 的实时性能,我们设计了针对 RTOS 核心指标的性能基准测试体系。测试重点关注时间确定性和系统响应的可预测性,这是实时操作系统区别于通用操作系统的关键特征。我们选择了四项核心指标进行评估:中断延时测试验证系统对外部事件的响应速度,响应时间测试评估任务调度的实时性,上下文切换时间测试衡量线程切换效率,线程启动时间测试检验系统资源分配性能。这些测试不仅帮助我们发现性能瓶颈和优化空间,更重要的是为系统的实时性保证提供了量化依据,确保 RusT-Thread 能够满足嵌入式和工业控制应用的严格时间要求。

中断延时测试

我们利用 Cortex-M 内核自带的 SysTick(系统滴答定时器)来精确测量中断延时。SysTick本质上是一个 24 位的硬件自减计数器。其工作原理如下:

计数与触发:计数器以系统时钟频率从一个预设的重载值(Reload Value)开始递减。当计数值从 1 减到 0 时,硬件会立即触发 SysTick 中断

自动重载:在触发中断的同一时钟周期,硬件会自动将重载值重新加载到计数器中,使其无缝开始下一轮递减,整个过程无需任何软件干预

由于中断服务程序的执行会存在微小的延迟,而 SysTick 计数器在此期间并未停止。因此,我们可以在中断服务程序的入口处,立即读取此刻 SysTick 计数器的当前值。通过这个差 值,我们就能精确计算出中断延时。计算公式为:

4592f65a-6f4d-11f0-9080-92fbcf53809c.png

我们系统测得 1000 次平均中断延时为 1.21us

响应时间测试

事件响应时间是指从事件发生到系统完成相应处理的总时间,包括事件检测、任务调度和执行处理逻辑的全过程。此指标衡量了系统对外部事件的端到端处理能力,是评估实时操作系统性能的综合指标。

在我们的测试中,使用随机数生成器模拟事件的随机生成,每隔相同时间生成一个随机数并于一个给定的概率值比较,当小于此概率值时,就生成一个事件,此事件的优先级也为随机数,可以证明,事件的间隔服从泊松分布。

我们将事件分为三种优先级:高中低,同时创建三个不同优先级的处理程序来处理事件,测量平均响应时间和各优先级的响应时间,结果如下:

45a4710a-6f4d-11f0-9080-92fbcf53809c.jpg

一般硬实时操作系统响应时间的指标为:

| 优先级 | 高 | 中 | 低 ||:----------: | |:--: | ||响应时间(us)|1~5 |5~20|20~100|

可以看到我们三种优先级事件的响应时间均符合硬实时操作系统的要求。

上下文切换时间测试

上下文切换时间是指操作系统从一个线程切换到另一个线程所需的时间,包括保存当前线程状态和恢复目标线程状态的过程。该指标对多任务系统的整体性能有显著影响,它决定了系统在任务间切换的效率。上下文切换时间越短,系统在高负载下的响应性越好,尤其在资源受限的嵌入式系统中,高效的上下文切换能显著提高处理器利用率和系统吞吐量。

我们测试了两个相同优先级线程来回切换 5000 次的平均时间,并执行了 100 次这样的测试,求的线程切换的时间性能如下:

45b1805c-6f4d-11f0-9080-92fbcf53809c.jpg

线程创建时间测试

线程创建时间是指从发起创建线程请求到新线程可以被调度执行所需的时间。该指标反映了系统动态资源分配和任务管理的效率。在需要频繁创建临时任务的应用场景中(如 Web 服务器、动态负载系统),高效的线程创建机制可以显著降低系统开销,提高资源利用率。对于嵌入式实时系统,快速的线程创建能力也有助于系统在运行时更灵活地调整工作负载,适应变化的环境需求。

由于 flash 大小限制,单次测试创建 50 个线程的平均时间,再做 100 次测试求平均,得到测试结果如下:

45c5b900-6f4d-11f0-9080-92fbcf53809c.png

与 RT-Thread 性能对比

RT-Thread 官方给出了他们的性能测试结果如下图:

45d8db5c-6f4d-11f0-9080-92fbcf53809c.jpg

其测试基于的硬件平台是 Zynq 7020,该开发板的主频为 800MHz,而我们使用的 QEMU模拟的是 stm32f405 的开发板,主频为 168MHz ,在对比性能时应考虑相关的硬件资源。

| 指标 |RT-Thread|Rust-Thread| 折合后的等效时间 ||:------------: | |:---------: | || 中断延时(ns) | 321 | 1210 | 254 || 上下文切换(us) | 0.633 | 2.58 | 0.542 || 线程创建(us) | 2.969 | 2.60 | 0.546 |

综上,我们重写后的 RusT-Thread 操作系统的实时性与 RT-Thread 相当甚至更加优秀,这符合我们当初制定的性能提升的目标。


6

优缺点


1 优点

安全导向的设计语言。Rust 的所有权机制使得 RusT-Thread 操作系统在内存安全和并发安全上很有优势

高度模块化并且可以定制。在搭建 RusT-Thread 操作系统时,我们基于 Rust 语言特性,建立了可模块化的系统仓库,定义改写模块方便快捷

平台具备高度可扩展性,虽然目前仅支持 Cortex-M4 平台,但模块化的 Hardware 利于后续扩展平台

多样的算法特性选择。在线程调度上提供多种调度算法,如优先级、优先级 + RR 等;在内存管理上支持伙伴系统、小内存分配器等多种内存分配方式

性能优秀。在 Rust 改写后的系统线程上下文切换性能与原 C 程序性能相当

测试点丰富。我们对各个模块开发了功能测试程序,利于后续的调试开发


2 缺点

相关文档尚不完善。由于时间精力,我们暂未维护起完善的文档体系

Rust 所有权机制等致使代码可读性差。为开发带来一定困难

外设周边尚未开发支持

异常反馈系统尚不完善,待后续开发


6

总结与展望


历经数月的攻坚克难,RusT-Thread 项目终于迎来了阶段性成果。我们成功地将 RT-Thread Nano 内核的核心功能,包括线程调度、内存管理、中断处理、时钟服务、IPC 等,用 Rust语言进行了高质量的重构与实现。这不仅是一次技术栈的迁移,更是在嵌入式实时操作系统领域,对 Rust 语言安全性、并发性和现代语言特性的一次深度实践与验证。

核心成果:安全性与性能的双重提升

内存安全基石:最大的收获莫过于 Rust 强大的所有权系统和借用检查机制带来的根本性改变。通过RTIntrFreeCell等创新设计,我们有效解决了嵌入式系统中全局共享数据访问这一高危痛点,将数据竞争、野指针、缓冲区溢出等 C 时代常见的“幽灵”从编译期就扼杀在摇篮里。内核服务的错误处理也因Option / Result变得更加健壮和可预测。

性能不妥协:我们并非单纯追求“安全”而牺牲效率。精心优化的调度算法(如基于位图+FFS 的优先级调度、创新的多级反馈队列)、高效的小内存分配器实现,以及 Rust 零成本抽象的特性,共同确保了 RusT-Thread 在 QEMU 模拟环境下的性能指标(中断延时、上下文切换、线程创建、响应时间)与原版 C 实现的 RT-Thread Nano 相当甚至略有优势。这证明了 Rust 完全有能力胜任对实时性要求苛刻的嵌入式场景。

代码精简与清晰:Rust 的现代语言特性(如 trait、泛型、丰富的标准库容器)显著提升了代码的表达力和可维护性。最直观的体现是,在实现同等甚至更多功能(如更优的定时器二分查找算法)的前提下,Rust-Thread 的核心代码量(约 5500 行)相比原 C 版(约 9600 行)有了显著的精简。模块化设计和清晰的抽象也让代码结构更易于理解和扩展。

扎实的验证体系:我们构建了涵盖单元测试、集成测试和全面的性能基准测试(内存性 能、中断延时、响应时间、上下文切换、线程创建)的验证体系。详实的数据不仅证明了系统的功能正确性,也为性能优化和后续迭代提供了坚实基础。

挑战与突破:在“裸机”上驾驭 Rust

项目过程并非一帆风顺。调试手段匮乏时,我们深度依赖半宿主打印和内联汇编调试技巧;硬件对接和启动流程的复杂性,通过cortex-mcortex-m-rt等库结合内联汇编巧妙化解;汇编与 Rust 联合编译调试的难题,最终以内联汇编统一在 Rust 源码中的方案优雅解决;而困扰嵌入式开发的全局变量问题,则由RTIntrFreeCell+lazy_static的组合拳提供了安全可靠的 Rust 式解决方案。每一次挑战的克服,都加深了我们对 Rust 在嵌入式裸机环境应用的理解。

展望未来:构建更强大、更开放的 RusT-Thread 生态

RusT-Thread 的诞生只是一个起点,我们对其未来充满期待:

1. 功能深化与扩展:

丰富软件生态:系统性地移植 RT-Thread 社区成熟的核心软件包(网络协议栈lwIP/PicoTCP、文件系统 LittleFS/SPIFFS、GUI 组件等),是当务之急。我们将致力于构建标准化的 Rust-C 互操作层接口,让海量的现有 C 语言资源能更顺畅地融入 Rust 生态

高级内核特性:实现更完善的内存管理策略(Slab, MemHeap)、支持更丰富的 IPC 机制(消息队列、邮箱、事件集)、探索多核(SMP)支持将是内核层面的重要方向

人性化体验:当前错误处理主要透传底层错误码。未来计划引入结构化的 Rust-native 错误类型,并集成分级日志与堆栈追踪功能,让异常反馈更清晰、调试更高效

2. 生态建设与普及:

广泛的硬件支持:目前已在 Cortex-M4 上验证。下一步将适配更多主流架构如 Cortex- M0+/M3/M7 和 RISC-V,目标是覆盖更广泛的物联网和边缘计算硬件平台

清晰的开发者体验:完善多级文档体系是生态繁荣的关键:

代码级:维护详尽的 rustdoc API 文档,包含示例和安全性说明

模块级:编写硬件抽象层(HAL)指南、驱动移植教程、核心模块设计解析等

入门级:提供面向应用开发者的、易于上手的使用手册和丰富的示例项目,显著降低 Rust嵌入式开发的门槛

工具链优化:持续优化代码体积(如替换重型打印宏)、提升构建体验,并探索更好的调试支持集成(如更深入的 GDB 支持)

RusT-Thread 项目是一次勇敢的尝试,它证明了 Rust 在资源受限的实时操作系统领域不仅可行,更能带来显著的安全性和开发效率提升。我们重构的不仅是一套代码,更是在探索嵌入式系统开发的未来范式。代码已开源,这只是一个开始。我们热切期待更多对 Rust 和嵌入式系统感兴趣的开发者加入,共同打磨 RusT-Thread,将其打造成为一个真正安全、高效、易用的开源实时操作系统选择,为国产嵌入式基础软件生态注入新的活力!安全至上,性能无忧,Rust 让嵌入式未来更可期。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 内核
    +关注

    关注

    3

    文章

    1423

    浏览量

    41666
  • RT-Thread
    +关注

    关注

    32

    文章

    1439

    浏览量

    42345
  • Rust
    +关注

    关注

    1

    文章

    237

    浏览量

    7199
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    如何对RT-Thread内核有基本的了解?

    RT-Thread 的时钟管理以时钟节拍为基础,时钟节拍是 RT-Thread 操作系统中最小的时钟单位。
    的头像 发表于 07-19 10:12 ?7558次阅读
     如何对<b class='flag-5'>RT-Thread</b><b class='flag-5'>内核</b>有基本的了解?

    RT-Thread记录(二、RT-Thread内核启动流程)

    在前面我们RT-Thread Studio工程基础之上讲一讲RT-Thread内核启动流程.
    的头像 发表于 06-20 00:30 ?5897次阅读
    <b class='flag-5'>RT-Thread</b>记录(二、<b class='flag-5'>RT-Thread</b><b class='flag-5'>内核</b>启动流程)

    RT-Thread编程指南

    RT-Thread编程指南——RT-Thread开发组(2015-03-31)。RT-Thread做为国内有较大影响力的开源实时操作系统,本文是RT-Thread实时操作系统的编程指南
    发表于 11-26 16:06 ?0次下载

    RT-Thread 内核学习笔记 - 理解defunct僵尸线程

    RT-Thread 内核学习笔记 - 内核对象rt_objectRT-Thread 内核学习笔记 -
    发表于 01-25 18:19 ?9次下载
    <b class='flag-5'>RT-Thread</b> <b class='flag-5'>内核</b>学习笔记 - 理解defunct僵尸线程

    RT-Thread 内核学习笔记 - 设备模型rt_device的理解

    RT-Thread 内核学习笔记 - 内核对象rt_objectRT-Thread 内核学习笔记 -
    发表于 01-25 18:19 ?8次下载
    <b class='flag-5'>RT-Thread</b> <b class='flag-5'>内核</b>学习笔记 - 设备模型<b class='flag-5'>rt</b>_device的理解

    RT-Thread 内核学习笔记 - 内核对象链表结构深入理解

    RT-Thread 内核学习笔记 - 内核对象rt_objectRT-Thread 内核学习笔记 -
    发表于 01-25 18:23 ?6次下载
    <b class='flag-5'>RT-Thread</b> <b class='flag-5'>内核</b>学习笔记 - <b class='flag-5'>内核</b>对象链表结构深入理解

    RT-Thread 内核学习笔记 - 内核对象初始化链表组织方式

    RT-Thread 内核学习笔记 - 内核对象rt_objectRT-Thread 内核学习笔记 -
    发表于 01-25 18:24 ?3次下载
    <b class='flag-5'>RT-Thread</b> <b class='flag-5'>内核</b>学习笔记 - <b class='flag-5'>内核</b>对象初始化链表组织方式

    RT-Thread 内核学习笔记 - 内核对象操作API

    RT-Thread 内核学习笔记 - 内核对象rt_objectRT-Thread 内核学习笔记 -
    发表于 01-25 18:26 ?7次下载
    <b class='flag-5'>RT-Thread</b> <b class='flag-5'>内核</b>学习笔记 - <b class='flag-5'>内核</b>对象操作API

    2022 RT-Thread全球技术大会:RT-Thread软件包

    RT-Thread在2022年上半年新增几十个软件包:rtt-rust、LuatOS、gui-guider-demo。
    的头像 发表于 05-27 14:12 ?1327次阅读
    2022 <b class='flag-5'>RT-Thread</b>全球技术大会:<b class='flag-5'>RT-Thread</b>软件包

    大佬带你理解RT-Thread内核并上手实践

    内核是操作系统最重要的部分,学习RT-Thread也是从最基本的内核开始。 ? RT-Thread内核要怎么学?编者觉得首先应该是从软件架构
    发表于 06-30 17:10 ?1682次阅读

    RT-Thread文档_RT-Thread 简介

    RT-Thread文档_RT-Thread 简介
    发表于 02-22 18:22 ?5次下载
    <b class='flag-5'>RT-Thread</b>文档_<b class='flag-5'>RT-Thread</b> 简介

    RT-Thread文档_内核基础

    RT-Thread文档_内核基础
    发表于 02-22 18:28 ?1次下载
    <b class='flag-5'>RT-Thread</b>文档_<b class='flag-5'>内核</b>基础

    RT-Thread文档_内核移植

    RT-Thread文档_内核移植
    发表于 02-22 18:31 ?4次下载
    <b class='flag-5'>RT-Thread</b>文档_<b class='flag-5'>内核</b>移植

    RT-Thread文档_RT-Thread SMP 介绍与移植

    RT-Thread文档_RT-Thread SMP 介绍与移植
    发表于 02-22 18:31 ?9次下载
    <b class='flag-5'>RT-Thread</b>文档_<b class='flag-5'>RT-Thread</b> SMP 介绍与移植

    RT-Thread v5.0.2 发布

    ://github.com/RT-Thread/rt-thread/releases/tag/v5.0.2 RT-Thread 迎来了全新的版本 v5.0.2,自 v5.0.0?版本发布以来,
    的头像 发表于 10-10 18:45 ?2099次阅读
    <b class='flag-5'>RT-Thread</b> v5.0.2 发布