LTTit:可动态编程的分布式实时操作系统
lttit
lttit 是一个针对单片机多节点设计的实验性操作系统框架。
lttit通过CSC分布式协议栈实现数据包路由、类TCP可靠性和调用远程的方法,通过ccBPF实现动态编程改变运行的程序的逻辑。
”可动态编程的实验性分布式实时操作系统“这个名字太长了,我直接叫lttit为鸟群操作系统了,它的核心特征就是:
1.让多个节点协作形成一个整体
2.支持在运行时动态修改节点的程序逻辑
这个项目诞生的原因就是:我的电子垃圾太多了,为了不浪费,我想把一百块单片机当成一块来用
它大部分组件在Linux中开发,然后被我一个个移植集成到内存只有20KB的单片机上。
当然,20KB完全够用了,毕竟当年unix之父的电脑也就这点内存。
组件
我写了以下九个组件,每个组件你都可以很方便的移植修改,当然,发现了什么bug记得提个issue:
lttit 九大组件
| 序号 | 组件名称 | 功能定位 | 说明 |
|---|---|---|---|
| 1 | 数据结构库 | 基础容器 | 红黑树、Radix 树、链表、哈希表、栈、队列等,可独立移植。 |
| 2 | 内存管理库 | 多种内存分配算法 | 类 SLOB、红黑树 + 链表分配器、内存池、类 SLAB,适配小内存 MCU。 |
| 3 | RTOS 内核 | 实时调度与任务管理 | RT(红黑树)+ BE(位图 + 链表)双调度;支持信号量、互斥锁、消息队列、读写锁、定时器等。 |
| 4 | 文件系统 | 基本文件操作 | 支持 inode、目录、读写、同步等。 |
| 5 | Shell | 命令行交互 | 可扩展的 shell,支持本地命令与远程命令。 |
| 6 | 微型编辑器(svim) | 文件编辑 | 类 vim 的轻量编辑器,支持基本编辑操作。 |
| 7 | TCP/IP 协议栈 | 网络通信 | 实现基本功能以配合 CSC。 |
| 8 | 分布式协议栈 CSC | 多节点通信与协作 | CCNET:路由层(Dijkstra); SCP:轻量流控协议(连接管理、重传、窗口、保活); CCRPC:远程调用(自动代码生成)。 |
| 9 | ccBPF(编译器 + BPF VM) | 动态编程能力 | 类 eBPF 的 C 子集编译器 + BPF 虚拟机,支持运行时注入逻辑、map 全局状态、可扩展 builtin。 |
多说无益,不如看看我使用这些组件实现的一个demo吧。
试一试!
这个demo主要是:把两块单片机连接,实现远程互相调用对方的代码,查看对方的内存、线程运行情况什么的。
同时,可以对非本地节点注入本地编写的c语言子集代码,实现动态改变对方的运行逻辑的功能。
DEMO
硬件准备
stm32f103c8t6最小系统板两块就行,下载器一块,串口模块一个,几根杜邦线,再加上一块面包板就行。


接线
两块单片机,分为节点nodeA和nodeB。
串口模块连接我们的电脑,使用串口助手mabaxterm即可。
然后这样接线:
pc和nodeA:
| PC(USB‑TTL 模块) | NodeA(STM32F103C8T6) |
|---|---|
| TX | PA10(USART1_RX) |
| RX | PA9(USART1_TX) |
| GND | GND |
| 5V(可选) | 5V |
TX与RX 交叉连接,波特率建议:115200
nodeA和nodeB
| NodeA(USART2) | NodeB(USART1) |
|---|---|
| PA2(USART2_TX) | PA10(USART1_RX) |
| PA3(USART2_RX) | PA9(USART1_TX) |
| GND | GND |
同样是 TX ↔ RX 交叉连接,两块板必须共地。
拉取工程
你可以去我的GitHub下载对应的demo工程,使用clion打开,进行配置然后编译。
分别打开nodeA和nodeB的工程后,让我们烧录程序到单片机中。
我们可以在mabaxterm中通过shell对我们的节点进行操作,比如:打开文件并且编辑、使用remote命令查看非本地节点的内存使用状况,远程调用ls命令查看远程节点目录下的文件。
远程操作
我在这里实现了一个shell命令,可以让单片机nodeA读取单片机nodeB的hello.c文件内容并且返回,然后nodeA的串口打印出这些内容.
很多人可能会觉得我用了什么单片机特性,其实就是很简单的过程,双方定义了RPC(远程调用)方法,nodeA发送消息到nodeB,nodeB看到后解析,然后执行解析出来的命令,再把文件内容封装为消息,通过CSC协议栈发送给nodeA,然后nodeA打印:
ccBPF
ccBPF是我受到Linux近几年新流行的技术eBPF启发而创作的组件,我们可以动态编辑节点的程序逻辑,而无需反复烧录。
由于stm32f103c8t6的内存实在是太小了,20KB还是有点不够,因此我不得不先使用nodeA跑ccBPF和文件系统,把我们的c子集程序进行编译,然后存入文件系统中,再重新跑我们的分布式组件,从文件系统中读取内容,然后远程注入到nodeB中。
它支持基本的c子集语法,有map这些全局状态操作,而且非常容易更改,你可以把你自己的本地函数添加到编译器中,这样,你就可以使用本地的函数了。
比如说,你想实现分布式计算,那么,你可以先在单片机中实现矩阵基本运算,更改一下编译器和虚拟机,把对应的运算函数加入到解析中,你在远程编程时,就可以使用这些函数了。
编译器和虚拟机仅仅是把这些函数看成一个符号,虚拟机执行时,会直接执行你自己定义的函数。
所以,从另一个方面来说,ccBPF其实比eBPF要强大很多,因为用户可以自由动态编程。
好了,看看我们的ccBPF的demo吧:
两大核心
整个操作系统的两大核心是分布式协议栈CSC和动态编程组件ccBPF。
CSC将不同的节点纳入体系内,提供对外的能力。
ccBPF动态更改运行节点的程序逻辑,比如换一种防火墙、换一种流量限速策略,甚至是:换一种调度策略。
可以把分布式协议看成一个发射器,动态更改目标节点的程序逻辑。
整个操作系统其实可以作为一个动态可编程平面的雏形。
极简与模块化设计
我遵循的是极简与模块化设计,在我看来,大部分项目,理解百分之二的代码就可以理解整个系统的运行。
很多知名的开源项目,虽然代码洋洋洒洒写了数万行,其实核心就一千来行,如果追求最简与能跑,几百行代码就可以写一个最小核心出来了。
我写的以上的所有组件,总代码量一万多行吧。
每个组件都是单独开发,可以在单片机上独运行的,你想要移植的话,复制粘贴一下,写一下接口就行了。
分布式
整个操作系统与其说是一个os,不如说像框架,你可以让编译器跑在Linux上,让文件系统跑在另一个单片机上甚至是PC上,每个组件都可以运行在不同的硬件上。
每个组件都不是一个分布式操作系统,但是当这些运行在Linux上、运行在单片机上的组件开始交互时,真正的分布式实时操作系统便从中显现。
可编程平面与分布式计算
我甚至在思考,其实可以分解任务,分发计算逻辑到不同的节点。
当然,我只是在嵌入式单片机上提供一个分布式编程平台,至于在上面开发应用则不是我的事情。
好的,就到这里吧,欢迎使用lttit,遇到问题,欢迎反馈。
如果你想在自己的作品中使用lttit,我很乐意为你解决lttit使用相关的问题。
参考
shell和编辑器由于只是交互外壳,红黑树、radix树、哈希表这些参考教科书和开源的实现比较多,由于是通用设计,就不过多说明了。
主要参考:
1.RTOS内核参考:FreeRTOS(源码)、Linux内核(代码风格)、QNX(设计理念)、rtems(调度框架设计)
2.内存管理参考:Linux内存管理算法slab、slob等设计
3.TCP/IP协议栈:参考4.4BSD-lite的TCP/IP协议栈,理论参考《TCP/IP详解》
4.CSC三层协议栈:参考4.4BSD-lite协议栈,其中ccRPC参考的是4.4BSD-lite的sun RPC
5.文件系统:参考4.4BSD-lite的unix 文件系统
6.ccBPF:编译器参考龙书,虚拟机参考4.4BSD-lite的BPF虚拟机,Linux内核的eBPF(设计理念)
BSD系列操作系统对我的影响其实是非常深刻的,我个人也非常喜欢FreeBSD的设计,代码非常优雅且模块化。