STVM OSAL 层架构设计文档

STVM OSAL 层架构设计文档

软仓地址:https://gitee.com/galaxy_0/stvm


0. 架构总览

0.1 三层结构

#mermaid-svg-Ghc51OHw7uksTwHw{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Ghc51OHw7uksTwHw .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Ghc51OHw7uksTwHw .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Ghc51OHw7uksTwHw .error-icon{fill:#552222;}#mermaid-svg-Ghc51OHw7uksTwHw .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Ghc51OHw7uksTwHw .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Ghc51OHw7uksTwHw .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Ghc51OHw7uksTwHw .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Ghc51OHw7uksTwHw .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Ghc51OHw7uksTwHw .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Ghc51OHw7uksTwHw .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Ghc51OHw7uksTwHw .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Ghc51OHw7uksTwHw .marker.cross{stroke:#333333;}#mermaid-svg-Ghc51OHw7uksTwHw svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Ghc51OHw7uksTwHw p{margin:0;}#mermaid-svg-Ghc51OHw7uksTwHw .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-Ghc51OHw7uksTwHw .cluster-label text{fill:#333;}#mermaid-svg-Ghc51OHw7uksTwHw .cluster-label span{color:#333;}#mermaid-svg-Ghc51OHw7uksTwHw .cluster-label span p{background-color:transparent;}#mermaid-svg-Ghc51OHw7uksTwHw .label text,#mermaid-svg-Ghc51OHw7uksTwHw span{fill:#333;color:#333;}#mermaid-svg-Ghc51OHw7uksTwHw .node rect,#mermaid-svg-Ghc51OHw7uksTwHw .node circle,#mermaid-svg-Ghc51OHw7uksTwHw .node ellipse,#mermaid-svg-Ghc51OHw7uksTwHw .node polygon,#mermaid-svg-Ghc51OHw7uksTwHw .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Ghc51OHw7uksTwHw .rough-node .label text,#mermaid-svg-Ghc51OHw7uksTwHw .node .label text,#mermaid-svg-Ghc51OHw7uksTwHw .image-shape .label,#mermaid-svg-Ghc51OHw7uksTwHw .icon-shape .label{text-anchor:middle;}#mermaid-svg-Ghc51OHw7uksTwHw .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Ghc51OHw7uksTwHw .rough-node .label,#mermaid-svg-Ghc51OHw7uksTwHw .node .label,#mermaid-svg-Ghc51OHw7uksTwHw .image-shape .label,#mermaid-svg-Ghc51OHw7uksTwHw .icon-shape .label{text-align:center;}#mermaid-svg-Ghc51OHw7uksTwHw .node.clickable{cursor:pointer;}#mermaid-svg-Ghc51OHw7uksTwHw .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Ghc51OHw7uksTwHw .arrowheadPath{fill:#333333;}#mermaid-svg-Ghc51OHw7uksTwHw .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Ghc51OHw7uksTwHw .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Ghc51OHw7uksTwHw .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Ghc51OHw7uksTwHw .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Ghc51OHw7uksTwHw .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Ghc51OHw7uksTwHw .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Ghc51OHw7uksTwHw .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Ghc51OHw7uksTwHw .cluster text{fill:#333;}#mermaid-svg-Ghc51OHw7uksTwHw .cluster span{color:#333;}#mermaid-svg-Ghc51OHw7uksTwHw div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-Ghc51OHw7uksTwHw .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Ghc51OHw7uksTwHw rect.text{fill:none;stroke-width:0;}#mermaid-svg-Ghc51OHw7uksTwHw .icon-shape,#mermaid-svg-Ghc51OHw7uksTwHw .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Ghc51OHw7uksTwHw .icon-shape p,#mermaid-svg-Ghc51OHw7uksTwHw .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Ghc51OHw7uksTwHw .icon-shape .label rect,#mermaid-svg-Ghc51OHw7uksTwHw .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Ghc51OHw7uksTwHw .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Ghc51OHw7uksTwHw .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Ghc51OHw7uksTwHw :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 唯一依赖入口
include osal.hpp

调用 13 个函数
OSAL 抽象层 ------ 1 个接口头 + 7 个后端实现
osal.hpp

4 类 13 个函数
osal.cpp 默认空实现
osal_linux.cpp

普通 / PREEMPT_RT / Xenomai
osal_windows.cpp

MSVC / MinGW
osal_freertos.cpp

V10+
osal_rtthread.cpp

v4.x+
osal_vxworks.cpp

6.x / 7.x
STVM 核心运行时 ------ 零 OS 依赖
VM.cpp

指令执行循环
Scheduler.cpp

PLC 顺序扫描
BytecodeProgram

字节码内存模型
IecCodegen / IecSymbolTable

编译期,不进 lib
cpu_affinity.cpp

向后兼容 wrapper
宿主应用(自由选择 OS)
stvm-run (Linux 命令行)
STM32 FreeRTOS 任务
i.MX8M RT-Thread 线程
PREEMPT_RT PLC 主循环
SylixOS 国产系统
VxWorks 7 硬实时任务

0.2 依赖方向(单向、无环)

复制代码
宿主应用 → STVM 核心运行时 → OSAL 抽象层 → OS 后端实现
  ↑                                          ↓
  └──────────────────────────────────────────┘
                  无反向依赖

关键保证:

  • OSAL 后端可以独立替换(链接时选择)
  • STVM 核心 #include "stvm/osal.hpp",永远不会 #include <sched.h> / <windows.h> / <FreeRTOS.h>
  • 7 个后端实现文件内部用 #ifdef 保护------没有对应 OS 头文件时自动 fallback 到空实现,在任何平台都能编译通过

1. 核心运行时的零 OS 依赖设计

1.1 STVM 的 PLC 扫描模型天然隔离 OS

#mermaid-svg-iYHN3afb7vSN4uHd{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-iYHN3afb7vSN4uHd .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-iYHN3afb7vSN4uHd .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-iYHN3afb7vSN4uHd .error-icon{fill:#552222;}#mermaid-svg-iYHN3afb7vSN4uHd .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-iYHN3afb7vSN4uHd .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-iYHN3afb7vSN4uHd .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-iYHN3afb7vSN4uHd .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-iYHN3afb7vSN4uHd .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-iYHN3afb7vSN4uHd .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-iYHN3afb7vSN4uHd .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-iYHN3afb7vSN4uHd .marker{fill:#333333;stroke:#333333;}#mermaid-svg-iYHN3afb7vSN4uHd .marker.cross{stroke:#333333;}#mermaid-svg-iYHN3afb7vSN4uHd svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-iYHN3afb7vSN4uHd p{margin:0;}#mermaid-svg-iYHN3afb7vSN4uHd defs #statediagram-barbEnd{fill:#333333;stroke:#333333;}#mermaid-svg-iYHN3afb7vSN4uHd g.stateGroup text{fill:#9370DB;stroke:none;font-size:10px;}#mermaid-svg-iYHN3afb7vSN4uHd g.stateGroup text{fill:#333;stroke:none;font-size:10px;}#mermaid-svg-iYHN3afb7vSN4uHd g.stateGroup .state-title{font-weight:bolder;fill:#131300;}#mermaid-svg-iYHN3afb7vSN4uHd g.stateGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-iYHN3afb7vSN4uHd g.stateGroup line{stroke:#333333;stroke-width:1;}#mermaid-svg-iYHN3afb7vSN4uHd .transition{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-iYHN3afb7vSN4uHd .stateGroup .composit{fill:white;border-bottom:1px;}#mermaid-svg-iYHN3afb7vSN4uHd .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px;}#mermaid-svg-iYHN3afb7vSN4uHd .state-note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-iYHN3afb7vSN4uHd .state-note text{fill:black;stroke:none;font-size:10px;}#mermaid-svg-iYHN3afb7vSN4uHd .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-iYHN3afb7vSN4uHd .edgeLabel .label rect{fill:#ECECFF;opacity:0.5;}#mermaid-svg-iYHN3afb7vSN4uHd .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-iYHN3afb7vSN4uHd .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-iYHN3afb7vSN4uHd .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-iYHN3afb7vSN4uHd .edgeLabel .label text{fill:#333;}#mermaid-svg-iYHN3afb7vSN4uHd .label div .edgeLabel{color:#333;}#mermaid-svg-iYHN3afb7vSN4uHd .stateLabel text{fill:#131300;font-size:10px;font-weight:bold;}#mermaid-svg-iYHN3afb7vSN4uHd .node circle.state-start{fill:#333333;stroke:#333333;}#mermaid-svg-iYHN3afb7vSN4uHd .node .fork-join{fill:#333333;stroke:#333333;}#mermaid-svg-iYHN3afb7vSN4uHd .node circle.state-end{fill:#9370DB;stroke:white;stroke-width:1.5;}#mermaid-svg-iYHN3afb7vSN4uHd .end-state-inner{fill:white;stroke-width:1.5;}#mermaid-svg-iYHN3afb7vSN4uHd .node rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-iYHN3afb7vSN4uHd .node polygon{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-iYHN3afb7vSN4uHd #statediagram-barbEnd{fill:#333333;}#mermaid-svg-iYHN3afb7vSN4uHd .statediagram-cluster rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-iYHN3afb7vSN4uHd .cluster-label,#mermaid-svg-iYHN3afb7vSN4uHd .nodeLabel{color:#131300;}#mermaid-svg-iYHN3afb7vSN4uHd .statediagram-cluster rect.outer{rx:5px;ry:5px;}#mermaid-svg-iYHN3afb7vSN4uHd .statediagram-state .divider{stroke:#9370DB;}#mermaid-svg-iYHN3afb7vSN4uHd .statediagram-state .title-state{rx:5px;ry:5px;}#mermaid-svg-iYHN3afb7vSN4uHd .statediagram-cluster.statediagram-cluster .inner{fill:white;}#mermaid-svg-iYHN3afb7vSN4uHd .statediagram-cluster.statediagram-cluster-alt .inner{fill:#f0f0f0;}#mermaid-svg-iYHN3afb7vSN4uHd .statediagram-cluster .inner{rx:0;ry:0;}#mermaid-svg-iYHN3afb7vSN4uHd .statediagram-state rect.basic{rx:5px;ry:5px;}#mermaid-svg-iYHN3afb7vSN4uHd .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#f0f0f0;}#mermaid-svg-iYHN3afb7vSN4uHd .note-edge{stroke-dasharray:5;}#mermaid-svg-iYHN3afb7vSN4uHd .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-iYHN3afb7vSN4uHd .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-iYHN3afb7vSN4uHd .statediagram-note text{fill:black;}#mermaid-svg-iYHN3afb7vSN4uHd .statediagram-note .nodeLabel{color:black;}#mermaid-svg-iYHN3afb7vSN4uHd .statediagram .edgeLabel{color:red;}#mermaid-svg-iYHN3afb7vSN4uHd #dependencyStart,#mermaid-svg-iYHN3afb7vSN4uHd #dependencyEnd{fill:#333333;stroke:#333333;stroke-width:1;}#mermaid-svg-iYHN3afb7vSN4uHd .statediagramTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-iYHN3afb7vSN4uHd :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Scheduler 构造
首次 runOnce()
set_thread_affinity(cfg.cpu_affinity)
检查周期任务是否到期
clock_us_ += tick
所有任务 FINISHED / ERROR
Init
FirstRun
BindAffinity
顺序扫描所有 ready tasks
CheckPeriodic
AdvanceClock
Exit
主循环完全是

纯内存数据结构操作

无阻塞、无 sleep

无真实系统调用

Scheduler 的 clock_us_ 是虚拟时钟:

方式 API 调用 说明
默认(零 OS 依赖) 无 runOnce() 内部手动 clock_us_ += tick_us
可选真实时钟 osal::get_time_us() 宿主设置时,每个 runOnce() 前读一次
两者对比 虚拟时钟:确定性行为;真实时钟:受系统负载影响 PLC 硬实时要求通常用虚拟时钟

1.2 剥离前 vs 剥离后的依赖面

依赖类型 剥离前 剥离后 现在
多线程 API 无(好) 无 ✅ 保持
真实时钟 API 无(好) 无 ✅ 保持
CPU 亲和性 sched_setaffinity / SetThreadAffinityMask → osal::set_thread_affinity() ✅ 隔离
文件 IO std::fopen/fread/fwrite → osal::file_open/read/write ✅ 隔离
trace 输出 std::fopen → osal::file_open ✅ 隔离

2. OSAL API 详细设计

2.1 API 全景(4 类 13 个函数)

#mermaid-svg-jHMLG5K4wPflasqq{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-jHMLG5K4wPflasqq .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-jHMLG5K4wPflasqq .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-jHMLG5K4wPflasqq .error-icon{fill:#552222;}#mermaid-svg-jHMLG5K4wPflasqq .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-jHMLG5K4wPflasqq .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-jHMLG5K4wPflasqq .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-jHMLG5K4wPflasqq .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-jHMLG5K4wPflasqq .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-jHMLG5K4wPflasqq .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-jHMLG5K4wPflasqq .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-jHMLG5K4wPflasqq .marker{fill:#333333;stroke:#333333;}#mermaid-svg-jHMLG5K4wPflasqq .marker.cross{stroke:#333333;}#mermaid-svg-jHMLG5K4wPflasqq svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-jHMLG5K4wPflasqq p{margin:0;}#mermaid-svg-jHMLG5K4wPflasqq g.classGroup text{fill:#9370DB;stroke:none;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:10px;}#mermaid-svg-jHMLG5K4wPflasqq g.classGroup text .title{font-weight:bolder;}#mermaid-svg-jHMLG5K4wPflasqq .cluster-label text{fill:#333;}#mermaid-svg-jHMLG5K4wPflasqq .cluster-label span{color:#333;}#mermaid-svg-jHMLG5K4wPflasqq .cluster-label span p{background-color:transparent;}#mermaid-svg-jHMLG5K4wPflasqq .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-jHMLG5K4wPflasqq .cluster text{fill:#333;}#mermaid-svg-jHMLG5K4wPflasqq .cluster span{color:#333;}#mermaid-svg-jHMLG5K4wPflasqq .nodeLabel,#mermaid-svg-jHMLG5K4wPflasqq .edgeLabel{color:#131300;}#mermaid-svg-jHMLG5K4wPflasqq .edgeLabel .label rect{fill:#ECECFF;}#mermaid-svg-jHMLG5K4wPflasqq .label text{fill:#131300;}#mermaid-svg-jHMLG5K4wPflasqq .labelBkg{background:#ECECFF;}#mermaid-svg-jHMLG5K4wPflasqq .edgeLabel .label span{background:#ECECFF;}#mermaid-svg-jHMLG5K4wPflasqq .classTitle{font-weight:bolder;}#mermaid-svg-jHMLG5K4wPflasqq .node rect,#mermaid-svg-jHMLG5K4wPflasqq .node circle,#mermaid-svg-jHMLG5K4wPflasqq .node ellipse,#mermaid-svg-jHMLG5K4wPflasqq .node polygon,#mermaid-svg-jHMLG5K4wPflasqq .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-jHMLG5K4wPflasqq .divider{stroke:#9370DB;stroke-width:1;}#mermaid-svg-jHMLG5K4wPflasqq g.clickable{cursor:pointer;}#mermaid-svg-jHMLG5K4wPflasqq g.classGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-jHMLG5K4wPflasqq g.classGroup line{stroke:#9370DB;stroke-width:1;}#mermaid-svg-jHMLG5K4wPflasqq .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-jHMLG5K4wPflasqq .classLabel .label{fill:#9370DB;font-size:10px;}#mermaid-svg-jHMLG5K4wPflasqq .relation{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-jHMLG5K4wPflasqq .dashed-line{stroke-dasharray:3;}#mermaid-svg-jHMLG5K4wPflasqq .dotted-line{stroke-dasharray:1 2;}#mermaid-svg-jHMLG5K4wPflasqq #compositionStart,#mermaid-svg-jHMLG5K4wPflasqq .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-jHMLG5K4wPflasqq #compositionEnd,#mermaid-svg-jHMLG5K4wPflasqq .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-jHMLG5K4wPflasqq #dependencyStart,#mermaid-svg-jHMLG5K4wPflasqq .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-jHMLG5K4wPflasqq #dependencyStart,#mermaid-svg-jHMLG5K4wPflasqq .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-jHMLG5K4wPflasqq #extensionStart,#mermaid-svg-jHMLG5K4wPflasqq .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-jHMLG5K4wPflasqq #extensionEnd,#mermaid-svg-jHMLG5K4wPflasqq .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-jHMLG5K4wPflasqq #aggregationStart,#mermaid-svg-jHMLG5K4wPflasqq .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-jHMLG5K4wPflasqq #aggregationEnd,#mermaid-svg-jHMLG5K4wPflasqq .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-jHMLG5K4wPflasqq #lollipopStart,#mermaid-svg-jHMLG5K4wPflasqq .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-jHMLG5K4wPflasqq #lollipopEnd,#mermaid-svg-jHMLG5K4wPflasqq .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-jHMLG5K4wPflasqq .edgeTerminals{font-size:11px;line-height:initial;}#mermaid-svg-jHMLG5K4wPflasqq .classTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-jHMLG5K4wPflasqq .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-jHMLG5K4wPflasqq .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-jHMLG5K4wPflasqq :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} <<namespace>>
osal
+"get_time_us() : uint64_t"
+"file_open(path, mode) : FileHandle"
+"file_read(h, buf, n) : size_t"
+"file_write(h, buf, n) : size_t"
+"file_seek(h, off, whence) : int"
+"file_tell(h) : long"
+"file_close(h) : int"
+"set_thread_affinity(core_id) : bool"
+"reset_thread_affinity() : bool"
+"get_core_count() : int"
+"set_thread_priority(policy, priority) : bool"
+"reset_thread_priority() : bool"
<<typedef>>
FileHandle
uintptr_t
<<enum>>
OpenMode
ReadBinary
WriteBinary
<<enum>>
SchedPolicy
Other
Fifo
Rr

2.2 时基

cpp 复制代码
uint64_t get_time_us();
后端 实现 精度 备注
Linux 普通 clock_gettime(CLOCK_MONOTONIC) ~1μs 受 NTP 调整影响
Linux PREEMPT_RT clock_gettime(CLOCK_MONOTONIC_RAW) < 100ns 不受 NTP 影响,硬实时要求
Linux Xenomai clock_gettime(CLOCK_MONOTONIC) < 5μs 通过 RTDM 桥接 rt_clock
Windows QueryPerformanceCounter ~200ns 硬件计数器
FreeRTOS xTaskGetTickCount() * TICK_US tick 周期 默认 1ms,可配
RT-Thread rt_tick_get() * (1e6 / RT_TICK_PER_SECOND) tick 周期
VxWorks tickGet() * 1e6 / sysClkRateGet() tick 周期
空实现 返回 0 - Scheduler 用虚拟时钟

2.3 文件 IO

cpp 复制代码
using FileHandle = uintptr_t;     // opaque handle,不暴露底层 FILE*/fd
constexpr FileHandle INVALID_FILE = 0;

enum class OpenMode { ReadBinary, WriteBinary };

FileHandle file_open (const char* path, OpenMode mode);
size_t     file_read (FileHandle h, void* buf, size_t n);
size_t     file_write(FileHandle h, const void* buf, size_t n);
int        file_seek (FileHandle h, long offset, int whence);
long       file_tell (FileHandle h);
int        file_close(FileHandle h);
后端 FileHandle 实际值 实现
Linux / Windows FILE* std::fopen/fread/fwrite
SylixOS / FreeRTOS FatFs fd (int) POSIX open/read/write/lseek/close
RT-Thread fd (int) dfs POSIX 层 开箱即用
VxWorks FILE* fopen/fread/fwrite
FreeRTOS 无 FatFs / 裸机 INVALID_FILE 返回失败

2.4 CPU 亲和性

cpp 复制代码
bool set_thread_affinity(int core_id);   // -1 表示取消绑定
bool reset_thread_affinity();
int  get_core_count();
后端 API 粒度
Linux / SylixOS pthread_setaffinity_np 线程级(而非进程级)
Windows SetThreadAffinityMask 线程级
VxWorks 7 taskCpuSetAffinity 任务级
FreeRTOS ❌ false 原生不支持
RT-Thread v5.x rt_thread_setaffinity 线程级
空实现 false / 1 -

2.5 调度优先级

cpp 复制代码
enum class SchedPolicy { Other, Fifo, Rr };

bool set_thread_priority(SchedPolicy policy, int priority);
bool reset_thread_priority();

语义映射(核心难点):

OS 优先级语义 osal 映射
Linux SCHED_FIFO/RR: 1-99(越大越高) 直接用(osal Fifo + 50 → Linux SCHED_FIFO 50)
RT-Thread 数字越大越高(与 Linux 同向) 直接用
VxWorks 数字越小越高(与 Linux 反向!) 翻转:osal 50 → VxWorks 200(250-50)
FreeRTOS 数字越大越高 ❌ 返回 false(无 SCHED_OTHER/FIFO 区分语义)
Windows 不支持硬实时策略 ❌ false

3. 后端实现详解

3.1 文件布局

复制代码
src/platform/osal/
├── osal.cpp            ← 默认空实现(任何 OS 能链接)
├── osal_linux.cpp      ← Linux / WSL / Android / PREEMPT_RT / Xenomai
├── osal_windows.cpp    ← MSVC / MinGW
├── osal_freertos.cpp   ← FreeRTOS V10+
├── osal_rtthread.cpp   ← RT-Thread v4.x+
└── osal_vxworks.cpp    ← VxWorks 6.x / 7.x

3.2 #ifdef 保护策略

每个后端文件内部三层防护:

cpp 复制代码
// 层 1:OS 平台判断(最外层)
#if defined(__linux__) || defined(__APPLE__) || defined(__ANDROID__)

// 层 2:具体组件判断(FreeRTOS/RT-Thread/VxWorks 有条件编译的内部功能)
#if defined(configNUMBER_OF_CORES) && configNUMBER_OF_CORES > 1
    return configNUMBER_OF_CORES;
#endif

// 层 3:兜底------fallback 到空实现
#else   // !__linux__
namespace stvm::osal { /* 空实现 */ }
#endif

效果:

  • 在 Windows/MSVC 上只选 osal_windows.cpp,其他 6 个文件因 #ifdef 不满足整文件编译为空
  • 在 Linux 上选 osal_linux.cpp,其他文件同理自动空化
  • 避免链接多个后端产生符号冲突

3.3 Linux 后端:PREEMPT_RT / Xenomai 自动检测

#mermaid-svg-4ybpYbanr3n3ygid{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-4ybpYbanr3n3ygid .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-4ybpYbanr3n3ygid .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-4ybpYbanr3n3ygid .error-icon{fill:#552222;}#mermaid-svg-4ybpYbanr3n3ygid .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-4ybpYbanr3n3ygid .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-4ybpYbanr3n3ygid .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-4ybpYbanr3n3ygid .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-4ybpYbanr3n3ygid .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-4ybpYbanr3n3ygid .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-4ybpYbanr3n3ygid .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-4ybpYbanr3n3ygid .marker{fill:#333333;stroke:#333333;}#mermaid-svg-4ybpYbanr3n3ygid .marker.cross{stroke:#333333;}#mermaid-svg-4ybpYbanr3n3ygid svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-4ybpYbanr3n3ygid p{margin:0;}#mermaid-svg-4ybpYbanr3n3ygid .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-4ybpYbanr3n3ygid .cluster-label text{fill:#333;}#mermaid-svg-4ybpYbanr3n3ygid .cluster-label span{color:#333;}#mermaid-svg-4ybpYbanr3n3ygid .cluster-label span p{background-color:transparent;}#mermaid-svg-4ybpYbanr3n3ygid .label text,#mermaid-svg-4ybpYbanr3n3ygid span{fill:#333;color:#333;}#mermaid-svg-4ybpYbanr3n3ygid .node rect,#mermaid-svg-4ybpYbanr3n3ygid .node circle,#mermaid-svg-4ybpYbanr3n3ygid .node ellipse,#mermaid-svg-4ybpYbanr3n3ygid .node polygon,#mermaid-svg-4ybpYbanr3n3ygid .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-4ybpYbanr3n3ygid .rough-node .label text,#mermaid-svg-4ybpYbanr3n3ygid .node .label text,#mermaid-svg-4ybpYbanr3n3ygid .image-shape .label,#mermaid-svg-4ybpYbanr3n3ygid .icon-shape .label{text-anchor:middle;}#mermaid-svg-4ybpYbanr3n3ygid .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-4ybpYbanr3n3ygid .rough-node .label,#mermaid-svg-4ybpYbanr3n3ygid .node .label,#mermaid-svg-4ybpYbanr3n3ygid .image-shape .label,#mermaid-svg-4ybpYbanr3n3ygid .icon-shape .label{text-align:center;}#mermaid-svg-4ybpYbanr3n3ygid .node.clickable{cursor:pointer;}#mermaid-svg-4ybpYbanr3n3ygid .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-4ybpYbanr3n3ygid .arrowheadPath{fill:#333333;}#mermaid-svg-4ybpYbanr3n3ygid .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-4ybpYbanr3n3ygid .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-4ybpYbanr3n3ygid .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-4ybpYbanr3n3ygid .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-4ybpYbanr3n3ygid .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-4ybpYbanr3n3ygid .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-4ybpYbanr3n3ygid .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-4ybpYbanr3n3ygid .cluster text{fill:#333;}#mermaid-svg-4ybpYbanr3n3ygid .cluster span{color:#333;}#mermaid-svg-4ybpYbanr3n3ygid div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-4ybpYbanr3n3ygid .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-4ybpYbanr3n3ygid rect.text{fill:none;stroke-width:0;}#mermaid-svg-4ybpYbanr3n3ygid .icon-shape,#mermaid-svg-4ybpYbanr3n3ygid .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-4ybpYbanr3n3ygid .icon-shape p,#mermaid-svg-4ybpYbanr3n3ygid .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-4ybpYbanr3n3ygid .icon-shape .label rect,#mermaid-svg-4ybpYbanr3n3ygid .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-4ybpYbanr3n3ygid .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-4ybpYbanr3n3ygid .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-4ybpYbanr3n3ygid :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} XENO_SKIN 宏存在
/sys/kernel/realtime = 1
其他
osal_linux.cpp 加载
detectKernel

运行时检查
Xenomai

CLOCK_MONOTONIC

SCHED_FIFO 生效
PREEMPT_RT

CLOCK_MONOTONIC_RAW

SCHED_FIFO 生效
普通 Linux

CLOCK_MONOTONIC

SCHED_FIFO 可设但效果非实时

关键代码(osal_linux.cpp):

cpp 复制代码
static LinuxKernelType detectKernel() {
#ifdef __XENO_SKIN__
    return LinuxKernelType::Xenomai;
#else
    std::ifstream rt("/sys/kernel/realtime");
    if (!rt) return LinuxKernelType::Normal;
    int v = 0; rt >> v;
    return (v == 1) ? LinuxKernelType::PreemptRt : LinuxKernelType::Normal;
#endif
}
static const LinuxKernelType kKernelType = detectKernel();  // 进程启动时检测一次

3.4 VxWorks 后端:优先级语义翻转

VxWorks 的优先级语义(数字越小越高)与 Linux/RT-Thread(数字越大越高)完全相反。osal 接口统一用"越大越高"语义,VxWorks 后端需要内部翻转:

cpp 复制代码
bool set_thread_priority(SchedPolicy, int priority) {
    // osal priority 0..99(越大越高)→ VxWorks priority 250..151(越小越高)
    int vx_prio = 250 - std::max(0, std::min(99, priority));
    return taskPrioritySet(taskIdSelf(), vx_prio) == OK;
}
osal priority VxWorks priority 含义
0 250 最低(接近 idle)
50 200 中等
99 151 最高(给中断/系统任务留 0-150)

3.5 RT-Thread 后端:dfs POSIX 开箱即用

RT-Thread 的 dfs(device file system)提供完整 POSIX 兼容层 ,包括 open/read/write/lseek/close------不需要额外挂载 FatFs,osal 的文件 IO 直接可用。

cpp 复制代码
#include "dfs_posix.h"   // POSIX 兼容层
FileHandle file_open(const char* path, OpenMode mode) {
    int flags = (mode == OpenMode::ReadBinary) ? O_RDONLY
                                               : (O_WRONLY | O_CREAT | O_TRUNC);
    return static_cast<FileHandle>(::open(path, flags, 0));
}

3.6 FreeRTOS 后端:可选 FatFs

FreeRTOS 原生没有文件系统。文件 IO 需要宿主额外挂载 FatFs/LittleFS:

cmake 复制代码
# 有 FatFs 时
cmake -DSTVM_OSAL_BACKEND=FREERTOS -DSTVM_FREERTOS_HAS_FATFS=1 ..
cpp 复制代码
#if defined(STVM_FREERTOS_HAS_FATFS)
#  include <fcntl.h>
#  include <unistd.h>
FileHandle file_open(const char* path, OpenMode mode) { ... ::open(path, flags, 0644) ... }
#else
FileHandle file_open(const char*, OpenMode) { return INVALID_FILE; }  // 空实现
#endif

4. CMake 集成

4.1 自动检测流程图

#mermaid-svg-Rcbae6HJaQgR6YmR{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Rcbae6HJaQgR6YmR .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Rcbae6HJaQgR6YmR .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Rcbae6HJaQgR6YmR .error-icon{fill:#552222;}#mermaid-svg-Rcbae6HJaQgR6YmR .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Rcbae6HJaQgR6YmR .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Rcbae6HJaQgR6YmR .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Rcbae6HJaQgR6YmR .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Rcbae6HJaQgR6YmR .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Rcbae6HJaQgR6YmR .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Rcbae6HJaQgR6YmR .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Rcbae6HJaQgR6YmR .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Rcbae6HJaQgR6YmR .marker.cross{stroke:#333333;}#mermaid-svg-Rcbae6HJaQgR6YmR svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Rcbae6HJaQgR6YmR p{margin:0;}#mermaid-svg-Rcbae6HJaQgR6YmR .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-Rcbae6HJaQgR6YmR .cluster-label text{fill:#333;}#mermaid-svg-Rcbae6HJaQgR6YmR .cluster-label span{color:#333;}#mermaid-svg-Rcbae6HJaQgR6YmR .cluster-label span p{background-color:transparent;}#mermaid-svg-Rcbae6HJaQgR6YmR .label text,#mermaid-svg-Rcbae6HJaQgR6YmR span{fill:#333;color:#333;}#mermaid-svg-Rcbae6HJaQgR6YmR .node rect,#mermaid-svg-Rcbae6HJaQgR6YmR .node circle,#mermaid-svg-Rcbae6HJaQgR6YmR .node ellipse,#mermaid-svg-Rcbae6HJaQgR6YmR .node polygon,#mermaid-svg-Rcbae6HJaQgR6YmR .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Rcbae6HJaQgR6YmR .rough-node .label text,#mermaid-svg-Rcbae6HJaQgR6YmR .node .label text,#mermaid-svg-Rcbae6HJaQgR6YmR .image-shape .label,#mermaid-svg-Rcbae6HJaQgR6YmR .icon-shape .label{text-anchor:middle;}#mermaid-svg-Rcbae6HJaQgR6YmR .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Rcbae6HJaQgR6YmR .rough-node .label,#mermaid-svg-Rcbae6HJaQgR6YmR .node .label,#mermaid-svg-Rcbae6HJaQgR6YmR .image-shape .label,#mermaid-svg-Rcbae6HJaQgR6YmR .icon-shape .label{text-align:center;}#mermaid-svg-Rcbae6HJaQgR6YmR .node.clickable{cursor:pointer;}#mermaid-svg-Rcbae6HJaQgR6YmR .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Rcbae6HJaQgR6YmR .arrowheadPath{fill:#333333;}#mermaid-svg-Rcbae6HJaQgR6YmR .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Rcbae6HJaQgR6YmR .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Rcbae6HJaQgR6YmR .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Rcbae6HJaQgR6YmR .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Rcbae6HJaQgR6YmR .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Rcbae6HJaQgR6YmR .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Rcbae6HJaQgR6YmR .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Rcbae6HJaQgR6YmR .cluster text{fill:#333;}#mermaid-svg-Rcbae6HJaQgR6YmR .cluster span{color:#333;}#mermaid-svg-Rcbae6HJaQgR6YmR div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-Rcbae6HJaQgR6YmR .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Rcbae6HJaQgR6YmR rect.text{fill:none;stroke-width:0;}#mermaid-svg-Rcbae6HJaQgR6YmR .icon-shape,#mermaid-svg-Rcbae6HJaQgR6YmR .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Rcbae6HJaQgR6YmR .icon-shape p,#mermaid-svg-Rcbae6HJaQgR6YmR .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Rcbae6HJaQgR6YmR .icon-shape .label rect,#mermaid-svg-Rcbae6HJaQgR6YmR .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Rcbae6HJaQgR6YmR .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Rcbae6HJaQgR6YmR .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Rcbae6HJaQgR6YmR :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 显式指定
AUTO 默认
Linux / Android
Windows
SylixOS
VxWorks
其他 / Generic
cmake ..
STVM_OSAL_BACKEND

AUTO/LINUX/WINDOWS/...
直接用指定值
CMAKE_SYSTEM_NAME?
osal_linux.cpp
osal_windows.cpp
osal_linux.cpp

POSIX 同 Linux
osal_vxworks.cpp
osal.cpp

默认空实现

4.2 CMake 核心代码(已在 CMakeLists.txt 中)

cmake 复制代码
# 选项(STRING cache 类型,因为 AUTO 是字符串而非布尔)
set(STVM_OSAL_BACKEND "AUTO" CACHE STRING "OSAL backend")
set_property(CACHE STVM_OSAL_BACKEND PROPERTY STRINGS
    AUTO LINUX WINDOWS FREERTOS RTTHREAD SYLIXOS VXWORKS BARE)

# 自动检测
if(STVM_OSAL_BACKEND STREQUAL "AUTO")
    if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
        set(_OSAL_BACKEND "LINUX")
    elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows")
        set(_OSAL_BACKEND "WINDOWS")
    ...
else()
    set(_OSAL_BACKEND "${STVM_OSAL_BACKEND}")
endif()

# 源文件选择(每个文件内部有 #ifdef 保护)
if(_OSAL_BACKEND STREQUAL "LINUX")
    list(APPEND STVM_SOURCES src/platform/osal/osal_linux.cpp)
elseif(...)
    ...
endif()
message(STATUS "OSAL backend : ${_OSAL_BACKEND}")

4.3 构建命令速查

场景 命令
Linux / WSL(自动检测) cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release ..
PREEMPT_RT 硬实时 同上(Linux 后端运行时自动检测 RT 内核)
SylixOS 交叉编译 cmake -DCMAKE_SYSTEM_NAME=SylixOS ..
FreeRTOS + FatFs cmake -DSTVM_OSAL_BACKEND=FREERTOS -DSTVM_FREERTOS_HAS_FATFS=1 -DFREERTOS_DIR=..
RT-Thread cmake -DSTVM_OSAL_BACKEND=RTTHREAD -DRTTHREAD_DIR=..
VxWorks 7 cmake -DSTVM_OSAL_BACKEND=VXWORKS -DCMAKE_C_COMPILER=cceppc ..
Windows MSVC cmake -G "Visual Studio 18 2026" ..

5. 核心代码改造点

5.1 改造清单(5 个文件)

#mermaid-svg-xctFIvYds9DZORyz{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-xctFIvYds9DZORyz .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-xctFIvYds9DZORyz .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-xctFIvYds9DZORyz .error-icon{fill:#552222;}#mermaid-svg-xctFIvYds9DZORyz .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-xctFIvYds9DZORyz .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-xctFIvYds9DZORyz .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-xctFIvYds9DZORyz .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-xctFIvYds9DZORyz .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-xctFIvYds9DZORyz .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-xctFIvYds9DZORyz .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-xctFIvYds9DZORyz .marker{fill:#333333;stroke:#333333;}#mermaid-svg-xctFIvYds9DZORyz .marker.cross{stroke:#333333;}#mermaid-svg-xctFIvYds9DZORyz svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-xctFIvYds9DZORyz p{margin:0;}#mermaid-svg-xctFIvYds9DZORyz .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-xctFIvYds9DZORyz .cluster-label text{fill:#333;}#mermaid-svg-xctFIvYds9DZORyz .cluster-label span{color:#333;}#mermaid-svg-xctFIvYds9DZORyz .cluster-label span p{background-color:transparent;}#mermaid-svg-xctFIvYds9DZORyz .label text,#mermaid-svg-xctFIvYds9DZORyz span{fill:#333;color:#333;}#mermaid-svg-xctFIvYds9DZORyz .node rect,#mermaid-svg-xctFIvYds9DZORyz .node circle,#mermaid-svg-xctFIvYds9DZORyz .node ellipse,#mermaid-svg-xctFIvYds9DZORyz .node polygon,#mermaid-svg-xctFIvYds9DZORyz .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-xctFIvYds9DZORyz .rough-node .label text,#mermaid-svg-xctFIvYds9DZORyz .node .label text,#mermaid-svg-xctFIvYds9DZORyz .image-shape .label,#mermaid-svg-xctFIvYds9DZORyz .icon-shape .label{text-anchor:middle;}#mermaid-svg-xctFIvYds9DZORyz .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-xctFIvYds9DZORyz .rough-node .label,#mermaid-svg-xctFIvYds9DZORyz .node .label,#mermaid-svg-xctFIvYds9DZORyz .image-shape .label,#mermaid-svg-xctFIvYds9DZORyz .icon-shape .label{text-align:center;}#mermaid-svg-xctFIvYds9DZORyz .node.clickable{cursor:pointer;}#mermaid-svg-xctFIvYds9DZORyz .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-xctFIvYds9DZORyz .arrowheadPath{fill:#333333;}#mermaid-svg-xctFIvYds9DZORyz .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-xctFIvYds9DZORyz .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-xctFIvYds9DZORyz .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-xctFIvYds9DZORyz .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-xctFIvYds9DZORyz .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-xctFIvYds9DZORyz .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-xctFIvYds9DZORyz .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-xctFIvYds9DZORyz .cluster text{fill:#333;}#mermaid-svg-xctFIvYds9DZORyz .cluster span{color:#333;}#mermaid-svg-xctFIvYds9DZORyz div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-xctFIvYds9DZORyz .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-xctFIvYds9DZORyz rect.text{fill:none;stroke-width:0;}#mermaid-svg-xctFIvYds9DZORyz .icon-shape,#mermaid-svg-xctFIvYds9DZORyz .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-xctFIvYds9DZORyz .icon-shape p,#mermaid-svg-xctFIvYds9DZORyz .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-xctFIvYds9DZORyz .icon-shape .label rect,#mermaid-svg-xctFIvYds9DZORyz .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-xctFIvYds9DZORyz .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-xctFIvYds9DZORyz .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-xctFIvYds9DZORyz :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 改造
剥离后
program.cpp

osal::file_open/read/write
VM.cpp L129

osal::file_open
Scheduler.cpp

cpu_affinity.hpp (wrapper)
cpu_affinity.cpp

→ 转发到 osal::
剥离前
program.cpp

std::fopen/fread/fwrite
VM.cpp L129

trace std::fopen
Scheduler.cpp

cpu_affinity.hpp
cpu_affinity.cpp

sched.h / Windows.h

5.2 向后兼容策略

#mermaid-svg-EENQ5nG2TJCqh7vx{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-EENQ5nG2TJCqh7vx .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-EENQ5nG2TJCqh7vx .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-EENQ5nG2TJCqh7vx .error-icon{fill:#552222;}#mermaid-svg-EENQ5nG2TJCqh7vx .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-EENQ5nG2TJCqh7vx .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-EENQ5nG2TJCqh7vx .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-EENQ5nG2TJCqh7vx .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-EENQ5nG2TJCqh7vx .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-EENQ5nG2TJCqh7vx .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-EENQ5nG2TJCqh7vx .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-EENQ5nG2TJCqh7vx .marker{fill:#333333;stroke:#333333;}#mermaid-svg-EENQ5nG2TJCqh7vx .marker.cross{stroke:#333333;}#mermaid-svg-EENQ5nG2TJCqh7vx svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-EENQ5nG2TJCqh7vx p{margin:0;}#mermaid-svg-EENQ5nG2TJCqh7vx .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-EENQ5nG2TJCqh7vx .cluster-label text{fill:#333;}#mermaid-svg-EENQ5nG2TJCqh7vx .cluster-label span{color:#333;}#mermaid-svg-EENQ5nG2TJCqh7vx .cluster-label span p{background-color:transparent;}#mermaid-svg-EENQ5nG2TJCqh7vx .label text,#mermaid-svg-EENQ5nG2TJCqh7vx span{fill:#333;color:#333;}#mermaid-svg-EENQ5nG2TJCqh7vx .node rect,#mermaid-svg-EENQ5nG2TJCqh7vx .node circle,#mermaid-svg-EENQ5nG2TJCqh7vx .node ellipse,#mermaid-svg-EENQ5nG2TJCqh7vx .node polygon,#mermaid-svg-EENQ5nG2TJCqh7vx .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-EENQ5nG2TJCqh7vx .rough-node .label text,#mermaid-svg-EENQ5nG2TJCqh7vx .node .label text,#mermaid-svg-EENQ5nG2TJCqh7vx .image-shape .label,#mermaid-svg-EENQ5nG2TJCqh7vx .icon-shape .label{text-anchor:middle;}#mermaid-svg-EENQ5nG2TJCqh7vx .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-EENQ5nG2TJCqh7vx .rough-node .label,#mermaid-svg-EENQ5nG2TJCqh7vx .node .label,#mermaid-svg-EENQ5nG2TJCqh7vx .image-shape .label,#mermaid-svg-EENQ5nG2TJCqh7vx .icon-shape .label{text-align:center;}#mermaid-svg-EENQ5nG2TJCqh7vx .node.clickable{cursor:pointer;}#mermaid-svg-EENQ5nG2TJCqh7vx .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-EENQ5nG2TJCqh7vx .arrowheadPath{fill:#333333;}#mermaid-svg-EENQ5nG2TJCqh7vx .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-EENQ5nG2TJCqh7vx .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-EENQ5nG2TJCqh7vx .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-EENQ5nG2TJCqh7vx .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-EENQ5nG2TJCqh7vx .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-EENQ5nG2TJCqh7vx .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-EENQ5nG2TJCqh7vx .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-EENQ5nG2TJCqh7vx .cluster text{fill:#333;}#mermaid-svg-EENQ5nG2TJCqh7vx .cluster span{color:#333;}#mermaid-svg-EENQ5nG2TJCqh7vx div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-EENQ5nG2TJCqh7vx .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-EENQ5nG2TJCqh7vx rect.text{fill:none;stroke-width:0;}#mermaid-svg-EENQ5nG2TJCqh7vx .icon-shape,#mermaid-svg-EENQ5nG2TJCqh7vx .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-EENQ5nG2TJCqh7vx .icon-shape p,#mermaid-svg-EENQ5nG2TJCqh7vx .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-EENQ5nG2TJCqh7vx .icon-shape .label rect,#mermaid-svg-EENQ5nG2TJCqh7vx .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-EENQ5nG2TJCqh7vx .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-EENQ5nG2TJCqh7vx .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-EENQ5nG2TJCqh7vx :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 旧 API(保留)
新 API(推荐)
cpu_affinity.cpp
转发到
#include stvm/osal.hpp
osal::set_thread_affinity()
#include stvm/platform/cpu_affinity.hpp
cpu_affinity::bindCurrentThread()

保留 cpu_affinity.hpp + cpu_affinity.cpp 作为向后兼容 wrapper,因为:

  • stvm_api.cpp 的 C API stvm_set_cpu_affinity() 暴露了旧命名空间
  • 外部宿主代码可能已 include 旧头文件
  • 单一实现点(osal 后端)避免跨平台代码重复

6. 实时 Linux 部署指南

6.1 推荐配置

#mermaid-svg-Gh5ShseVznNucnil{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Gh5ShseVznNucnil .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Gh5ShseVznNucnil .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Gh5ShseVznNucnil .error-icon{fill:#552222;}#mermaid-svg-Gh5ShseVznNucnil .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Gh5ShseVznNucnil .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Gh5ShseVznNucnil .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Gh5ShseVznNucnil .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Gh5ShseVznNucnil .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Gh5ShseVznNucnil .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Gh5ShseVznNucnil .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Gh5ShseVznNucnil .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Gh5ShseVznNucnil .marker.cross{stroke:#333333;}#mermaid-svg-Gh5ShseVznNucnil svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Gh5ShseVznNucnil p{margin:0;}#mermaid-svg-Gh5ShseVznNucnil .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-Gh5ShseVznNucnil .cluster-label text{fill:#333;}#mermaid-svg-Gh5ShseVznNucnil .cluster-label span{color:#333;}#mermaid-svg-Gh5ShseVznNucnil .cluster-label span p{background-color:transparent;}#mermaid-svg-Gh5ShseVznNucnil .label text,#mermaid-svg-Gh5ShseVznNucnil span{fill:#333;color:#333;}#mermaid-svg-Gh5ShseVznNucnil .node rect,#mermaid-svg-Gh5ShseVznNucnil .node circle,#mermaid-svg-Gh5ShseVznNucnil .node ellipse,#mermaid-svg-Gh5ShseVznNucnil .node polygon,#mermaid-svg-Gh5ShseVznNucnil .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Gh5ShseVznNucnil .rough-node .label text,#mermaid-svg-Gh5ShseVznNucnil .node .label text,#mermaid-svg-Gh5ShseVznNucnil .image-shape .label,#mermaid-svg-Gh5ShseVznNucnil .icon-shape .label{text-anchor:middle;}#mermaid-svg-Gh5ShseVznNucnil .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Gh5ShseVznNucnil .rough-node .label,#mermaid-svg-Gh5ShseVznNucnil .node .label,#mermaid-svg-Gh5ShseVznNucnil .image-shape .label,#mermaid-svg-Gh5ShseVznNucnil .icon-shape .label{text-align:center;}#mermaid-svg-Gh5ShseVznNucnil .node.clickable{cursor:pointer;}#mermaid-svg-Gh5ShseVznNucnil .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Gh5ShseVznNucnil .arrowheadPath{fill:#333333;}#mermaid-svg-Gh5ShseVznNucnil .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Gh5ShseVznNucnil .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Gh5ShseVznNucnil .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Gh5ShseVznNucnil .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Gh5ShseVznNucnil .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Gh5ShseVznNucnil .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Gh5ShseVznNucnil .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Gh5ShseVznNucnil .cluster text{fill:#333;}#mermaid-svg-Gh5ShseVznNucnil .cluster span{color:#333;}#mermaid-svg-Gh5ShseVznNucnil div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-Gh5ShseVznNucnil .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Gh5ShseVznNucnil rect.text{fill:none;stroke-width:0;}#mermaid-svg-Gh5ShseVznNucnil .icon-shape,#mermaid-svg-Gh5ShseVznNucnil .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Gh5ShseVznNucnil .icon-shape p,#mermaid-svg-Gh5ShseVznNucnil .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Gh5ShseVznNucnil .icon-shape .label rect,#mermaid-svg-Gh5ShseVznNucnil .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Gh5ShseVznNucnil .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Gh5ShseVznNucnil .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Gh5ShseVznNucnil :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} SCHED_FIFO 调度
PLC 任务 优先级 50-60
设备驱动 优先级 80+
系统守护 优先级 20-30
CPU 亲和性绑定
PLC 任务 → CPU 1
网卡驱动 → CPU 2
用户进程 → CPU 0
isolcpus=1 启动参数

(隔离 CPU 免受其他调度干扰)
PREEMPT_RT 内核
CONFIG_PREEMPT_RT_FULL=y
CONFIG_CPU_FREQ=n

(禁用频率调整)
CONFIG_HZ=1000
/sys/kernel/realtime = 1

6.2 宿主侧完整代码

cpp 复制代码
#include <csignal>
#include <stvm/osal.hpp>
#include <stvm/stvm.hpp>

int main() {
    // 1. 禁用本进程被 OOM killer 选中(嵌入式关键系统)
    // echo -1000 > /proc/self/oom_score_adj

    // 2. 禁止被 cgroup 限制(容器环境)

    // 3. 构造 bytecode(磁盘文件或内存)
    stvm::BytecodeProgram prog;
    std::string err;
    prog.readFromFile("plc.bytecode", err);

    // 4. 配置 Scheduler
    stvm::Scheduler sched;
    sched.addTask("PLC_Main", prog, 1000 /* 1ms 周期 */, 50000);

    // 5. 绑定到 CPU 1(isolcpus=1 已隔离)
    stvm::osal::set_thread_affinity(1);

    // 6. 提升调度优先级到 SCHED_FIFO 50
    stvm::osal::set_thread_priority(
        stvm::osal::SchedPolicy::Fifo, 50);

    // 7. 主循环(PREEMPT_RT 下 1ms 周期抖动 < 10μs)
    while (sched.runOnce()) { /* 纯计算,无阻塞 */ }

    return 0;
}

6.3 预期性能

场景 内核 1ms 周期抖动 最大延迟
普通 Ubuntu 5.15-generic ±100-300μs 不确定
PREEMPT_RT 5.10-rt-amd64 ±5-15μs < 50μs
Xenomai ipipe 双内核 ±1-5μs < 20μs

7. 后端横向对比

后端 时基 文件 IO CPU 亲和性 调度优先级 编译条件
Linux 普通 CLOCK_MONOTONIC ✅ fopen/fread ✅ pthread_setaffinity_np ⚠️ 可设但非实时 __linux__
Linux PREEMPT_RT CLOCK_MONOTONIC_RAW ✅ ✅ ✅ SCHED_FIFO 真实生效 运行时检测
Linux Xenomai CLOCK_MONOTONIC(RTDM) ✅ ✅ ✅ SCHED_FIFO __XENO_SKIN__
Windows QPC ~200ns ✅ fopen ✅ SetThreadAffinityMask ❌ false _WIN32
FreeRTOS tick * 1000 可选 FatFs ❌ false ❌ false __has_include(<FreeRTOS.h>)
RT-Thread tick * 1000 ✅ dfs POSIX v5.x 可选 ✅ rt_thread_set_priority __has_include(<rt-thread.h>)
SylixOS clock_gettime ✅ POSIX ✅ pthread_setaffinity_np ✅ pthread_setschedparam CMake SYLIXOS 分支
VxWorks 6 tickGet ✅ fopen ❌ false ✅ taskPrioritySet(翻转) __has_include(<vxWorks.h>)
VxWorks 7 tickGet ✅ ✅ taskCpuSetAffinity ✅ taskPrioritySet(翻转) VX_VERSION >= 0x70000000
默认空 返回 0 INVALID_FILE false false 无后端条件满足

8. 新增后端移植指南

宿主新增一个 OS 后端的 5 步流程:
#mermaid-svg-uJ4Papb7Dy180xiJ{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-uJ4Papb7Dy180xiJ .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-uJ4Papb7Dy180xiJ .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-uJ4Papb7Dy180xiJ .error-icon{fill:#552222;}#mermaid-svg-uJ4Papb7Dy180xiJ .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-uJ4Papb7Dy180xiJ .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-uJ4Papb7Dy180xiJ .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-uJ4Papb7Dy180xiJ .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-uJ4Papb7Dy180xiJ .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-uJ4Papb7Dy180xiJ .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-uJ4Papb7Dy180xiJ .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-uJ4Papb7Dy180xiJ .marker{fill:#333333;stroke:#333333;}#mermaid-svg-uJ4Papb7Dy180xiJ .marker.cross{stroke:#333333;}#mermaid-svg-uJ4Papb7Dy180xiJ svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-uJ4Papb7Dy180xiJ p{margin:0;}#mermaid-svg-uJ4Papb7Dy180xiJ .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-uJ4Papb7Dy180xiJ .cluster-label text{fill:#333;}#mermaid-svg-uJ4Papb7Dy180xiJ .cluster-label span{color:#333;}#mermaid-svg-uJ4Papb7Dy180xiJ .cluster-label span p{background-color:transparent;}#mermaid-svg-uJ4Papb7Dy180xiJ .label text,#mermaid-svg-uJ4Papb7Dy180xiJ span{fill:#333;color:#333;}#mermaid-svg-uJ4Papb7Dy180xiJ .node rect,#mermaid-svg-uJ4Papb7Dy180xiJ .node circle,#mermaid-svg-uJ4Papb7Dy180xiJ .node ellipse,#mermaid-svg-uJ4Papb7Dy180xiJ .node polygon,#mermaid-svg-uJ4Papb7Dy180xiJ .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-uJ4Papb7Dy180xiJ .rough-node .label text,#mermaid-svg-uJ4Papb7Dy180xiJ .node .label text,#mermaid-svg-uJ4Papb7Dy180xiJ .image-shape .label,#mermaid-svg-uJ4Papb7Dy180xiJ .icon-shape .label{text-anchor:middle;}#mermaid-svg-uJ4Papb7Dy180xiJ .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-uJ4Papb7Dy180xiJ .rough-node .label,#mermaid-svg-uJ4Papb7Dy180xiJ .node .label,#mermaid-svg-uJ4Papb7Dy180xiJ .image-shape .label,#mermaid-svg-uJ4Papb7Dy180xiJ .icon-shape .label{text-align:center;}#mermaid-svg-uJ4Papb7Dy180xiJ .node.clickable{cursor:pointer;}#mermaid-svg-uJ4Papb7Dy180xiJ .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-uJ4Papb7Dy180xiJ .arrowheadPath{fill:#333333;}#mermaid-svg-uJ4Papb7Dy180xiJ .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-uJ4Papb7Dy180xiJ .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-uJ4Papb7Dy180xiJ .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-uJ4Papb7Dy180xiJ .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-uJ4Papb7Dy180xiJ .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-uJ4Papb7Dy180xiJ .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-uJ4Papb7Dy180xiJ .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-uJ4Papb7Dy180xiJ .cluster text{fill:#333;}#mermaid-svg-uJ4Papb7Dy180xiJ .cluster span{color:#333;}#mermaid-svg-uJ4Papb7Dy180xiJ div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-uJ4Papb7Dy180xiJ .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-uJ4Papb7Dy180xiJ rect.text{fill:none;stroke-width:0;}#mermaid-svg-uJ4Papb7Dy180xiJ .icon-shape,#mermaid-svg-uJ4Papb7Dy180xiJ .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-uJ4Papb7Dy180xiJ .icon-shape p,#mermaid-svg-uJ4Papb7Dy180xiJ .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-uJ4Papb7Dy180xiJ .icon-shape .label rect,#mermaid-svg-uJ4Papb7Dy180xiJ .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-uJ4Papb7Dy180xiJ .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-uJ4Papb7Dy180xiJ .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-uJ4Papb7Dy180xiJ :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 1. 创建 osal_xxx.cpp
2. #ifdef 保护

没有对应 OS 头文件时

fallback 到空实现
3. 实现 4 类 13 个函数

时基/文件/亲和性/调度
4. CMakeLists.txt 加

elseif _OSAL_BACKEND STREQUAL XXX

  • list APPEND osal_xxx.cpp
  1. 宿主交叉编译

-DSTVM_OSAL_BACKEND=XXX


附录:验证结果

项目 结果
7 后端编译(Linux host) 全部 ✅
test_vm(Linux 后端) 74/74
test_bytecode(Linux 后端) 33/33
bench_perf(Linux 后端) 0 failures
BARE 后端 test_vm ✅ / test_bytecode ⚠️ 预期失败(无文件系统)
ASAN 检查 0 UB(Phase 1 已验证)
相关推荐
进化中的刀盾兽1 小时前
从零实现 C++ AI 大模型接入 SDK(九):LLMManager 统一模型管理与请求路由
c++
.YM.Z1 小时前
C++——【红黑树】原理详解:定义、性质、插入变色与旋转实现
开发语言·c++
无名猿2 小时前
constexpr 能力扩张:从 C++11 到 C++20 的编译期计算
c++·性能优化·现代c++·编译期
007张三丰2 小时前
C/C++ 内存管理详解:从内存分布到 new/delete 底层原理
java·c语言·c++·内存管理
调试优选官2 小时前
2026年物联网应用开发公司上榜品牌解析:D-coding技术纵深、项目规范与长期服务观察
物联网·开发经验·d-coding
白搞电子2 小时前
ESP32-S31 WASM 应用开发实录:重力弹球从电脑预览到 ESP-Mosaico 实机测试
单片机·嵌入式硬件·物联网·电脑·wasm
蓝天居士2 小时前
PY32F系列MCU在OTA时App区概率性跑不起来的根因分析(6)
mcu·嵌入式
三月微暖寻春笋3 小时前
【和春笋一起学C++】(七十二)类模板
开发语言·c++·实例·类模板·使用类模板·数组模板
xlq223223 小时前
全面复习4
c++