5.8 KiB
5.8 KiB
Nucleus RTOS:线性内存映射 + 保护域 / 动态模块生命周期
最反直觉的一条:存在 "process isolation"
≠ 采用 Linux 那种"每进程一个完全独立的虚拟地址世界"
Nucleus 的 Process Model:
- Cortex-A 上可用 MMU,Cortex-M 上可用 MPU
- 提供 space-domain partitioning(空间域分区) 与 entitlement(授权)
- 采用线性(flat)内存映射 + 受保护内存区域
- application 与 kernel module 可以动态 reload / restart / update,而不需要停掉整个系统
于是:
两个 process 里的地址看起来线性、接近 → 不能判"没有地址空间隔离"
同一地址 A 能访问、B fault → 可能只是 entitlement 不同
module 被替换而系统从未 reboot → 可能是正常的模块生命周期
判断隔离要看 MMU/MPU entitlement,而不是比较指针数值。 </CORE RULE>
一、Process Model 与 POSIX 心智模型的区别
要恢复的图是:
Nucleus Process
├─ modules
├─ tasks
├─ protected regions
└─ entitlements
而不是 PID → 页表 → fork 父进程 → exec ELF。Nucleus 的 "process" 重点是模块加载、内存访问保护、特权与隔离,不是复制 Linux process ABI。
- Cortex-M 上没有完整 MMU也能有 process 模型——靠 MPU region 重配置、特权级与 entitlement;"找不到页表"不能推出"没有 Process Model"
- 一个 process 出错不应默认全系统一起死:空间隔离的价值就是让故障恢复可以是"重启出错的 module/process,其他子系统继续"
二、术语坑:partition 有两种完全不同的含义
| 名称 | 含义 |
|---|---|
| Process Model 的 space partition | 进程/子系统的空间隔离域 |
NU_PARTITION_POOL |
固定大小内存块的分配器(memory partition pool) |
NU_Create_Partition_Pool(pool, name, start_address, pool_size, partition_size, suspend_type)
NU_Allocate_Partition(pool, &ptr, suspend)
NU_Deallocate_Partition(ptr)
这里的 partition 指的是"固定大小的内存块",与隔离域无关。看到 partition 这个词必须先分清是哪一种。
三、固定块分配器的语义(决定了"卡在分配器里"是否正常)
- 池是连续内存区 + 固定大小块(例如 2000 字节、块 40 字节 = 50 块)
- 分配是确定性的 O(1):不做搜索;不可能产生碎片,唯一的失败模式是该池真的耗尽
- suspend 选项:
NU_NO_SUSPEND:无论能否满足都立即返回;非任务线程(如Application_Initialize)只能用它NU_SUSPEND:调用任务挂起直到有块被归还- 超时值:挂起到有块或超时
- 多个任务挂起在同一池上时,按池创建时指定的 FIFO 或优先级顺序恢复
- 返回值
NU_NO_PARTITION表示"无法立即满足"
所以:
task 卡在分配器里、state = suspended
→ 用 NU_SUSPEND 且池空时,按语义本来就该挂起
→ 不是 heap deadlock
分配失败但系统 RAM 还剩很多
→ 固定池耗尽与通用堆无关,也不是"全局堆碎片"
四、动态模块生命周期
Nucleus 支持动态 reload / restart / update application 与 kernel modules,不影响其他 module、也不必 shutdown 整个系统。
于是固件时间线里出现:
module A 版本 X → 短暂停止 → module A 版本 Y
且全程没有 boot event
不能单凭这一点判"运行时注入 / rootkit 替换"——先查该系统的 module lifecycle/update 路径。
这与"单体嵌入式镜像:更新一块 → 整机重启"的传统假设不同。
决策树
拿到 Nucleus 目标
├─ 看到 "partition"
│ ├─ 是 Process Model 的空间隔离域?
│ └─ 还是 NU_PARTITION_POOL 固定块分配器?
├─ 两个"process"的地址看起来线性/接近
│ ├─ 线性内存映射 + 受保护区域就是该模型
│ └─ 判断隔离要看 entitlement,不是比地址
├─ 同一地址访问权限不同
│ └─ 符合 "同一线性地址 + 不同保护授权"
├─ Cortex-M 上没有页表
│ └─ 仍可有 process 模型(MPU + 特权 + entitlement)
├─ task 挂起在分配器里
│ ├─ 查是否用了 NU_SUSPEND 且池空
│ └─ 查池容量与归还路径,而不是堆死锁
├─ 分配失败但内存充足
│ └─ 固定池耗尽,与通用堆无关
└─ module 在无 reboot 的情况下被替换
└─ 查官方 module reload/update 生命周期
工具与验证
- 隔离:MMU/MPU 配置、受保护区域、entitlement 与特权状态
- 内存:partition pool 的块大小与块数、当前占用与等待者;区分它与通用堆
- 生命周期:模块加载/重载/更新的路径与版本变更点
- 验证:能同时说清「隔离靠 MMU 还是 MPU、授权是什么 + 该地址属于哪个域 + 分配失败是池耗尽还是堆问题」
该平台的坑(汇总)
- 用 Linux 每进程独立地址空间的模型理解隔离:这里是线性映射 + 受保护区域 + entitlement
- 比较指针数值判断是否共享内存:地址相同不代表内存共享
- 在 Cortex-M 上因找不到页表就否定 Process Model:MPU 也能构建隔离
- 把
partition一律理解为隔离域:NU_PARTITION_POOL是固定块分配器 - 把
NU_SUSPEND导致的挂起当 heap deadlock - 把固定池耗尽诊断为全局堆碎片:该分配器不产生碎片
- 把无 reboot 的 module 替换当注入:动态 reload/restart/update 是既有能力
- 在非任务线程里用
NU_SUSPEND:只允许NU_NO_SUSPEND - 默认 process 出错就是全系统复位:隔离的意义正是局部恢复
- 期待 fork/exec/mmap 语义:那不是这个 process 模型的重点