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最小系统板两块就行,下载器一块,串口模块一个,几根杜邦线,再加上一块面包板就行。

imgimg

接线

两块单片机,分为节点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的设计,代码非常优雅且模块化。