novus文档手册
设备管理器(M12,devmgmt)
Novus OS 的 Windows 11 设备管理器复刻:主窗口是菜单栏 + 工具栏 + 左侧可折叠 设备树 + 状态栏;双击/右键"属性"打开一个独立的模态属性子窗口(常规 / 驱动程序 / 详细信息 / 事件 / 资源),版式完全对齐 Win11。所有信息来自内核在启动期归一化的 设备表,应用本身不扫硬件。
状态:随 M12 生效 适用范围:内核
kernel/devtab.{h,c}、kernel/sysinfo.{h,c}、kernel/usb.{h,c}窗口管理器wm/novus-wm/nwm.c与apps/src/wm.rs应用apps/src/devmgr/{mod,tree,props,fields}.rs、apps/src/bin/devmgmt.rs
1. 入口
设备管理器可从四个入口启动,全部走 apps_launch() 按名字解析(devmgmt):
- 桌面右侧磁贴(与文件管理器/任务管理器/设置/网络/终端/安装并列,常驻);
- 底部任务栏固定图标(含运行时强调色指示圆点);
- 开始菜单"设备管理器"按钮;
nsh终端直接输入devmgmt。
kernel/session.c 的 desktop_app() 白名单与 apps.c 应用表都已登记,未登录时
apps_launch() 同样拒绝普通桌面应用。设置面板的"应用"页也把它列入"可启动"
(固定顺序:文件管理器/任务管理器/设置/设备管理器)。
2. 架构
kernel/devtab.c ── 启动期建表(PCI 缓存 + blkdev/net/display/CPU/ACPI/USB/IOAPIC/PS2)
│ devtab_count / devtab_at / devtab_field_count / devtab_field_at
kernel/sysinfo.c ── REQ_DEVLIST(0x031B) / REQ_DEVFIELD(0x031D),128 B 分页
│ IPC
apps/src/sinfo.rs ── devices() / dev_fields()
apps/src/devmgr/* ── 主窗 + 设备树 + 模态属性窗
│ wm::Win::create_ex(..., NWM_F_CREATE_MODAL) / next_event_any()
wm/novus-wm/nwm.c ── 120/160 显示列表预算、10 窗口、模态输入隔离
设计要点:
- 设备表固化:
devtab_init()放在ide_init()之后、net_init()之前 (此时存储已就绪但无 DMA 在途);网卡在net_init()之后用devtab_refresh()追加。devtab规模DEV_MAX 48、PCI_MAX_DEVICES 32,约 2.3 KB + 4 KB,零运行期 BAR 探测副作用。 - 字段分页:设备详情(实例路径、硬件 ID、资源范围)长度远超 128 B,改为
(dev, tab, index)逐条取字段,客户端缓存当前页(2 条/包,值 56 字节,长文本截断)。 - 模态子窗口:属性窗是独立窗口 +
NWM_F_CREATE_MODAL;WM 在模态窗存在时把指针 与键盘只路由给它,其它应用零改动。
3. 协议契约
设备树节点(sysinfo_dev_t,40 B,3 条/包 = 4 + 120):
| 字段 | 类型 | 说明 |
|---|---|---|
parent |
u16 | 父类别节点下标,0xFFFF 表示根 |
class_id |
u8 | DEV_CAT_*(计算机/处理器/固件/显示/磁盘/存储控制器/网络/USB/输入/系统设备/未知) |
status |
u8 | DEV_STATUS_OK / DEV_STATUS_WARN(无驱动或未知设备) |
kind |
u8 | DEV_KIND_*(CPU/PCI/显卡/监视器/磁盘/网卡/USB 控制器/USB 设备/输入/系统/固件…) |
idx |
u8 | 在所属子系统表中的下标(取 BAR/事件/扇区用) |
flags |
u8 | DEV_FLAG_REMOVABLE / DEV_FLAG_NODRV 等 |
name |
char[32] | UTF-8 名称 |
属性字段(sysinfo_devfield_t,60 B,2 条/包 = 4 + 120):
| 字段 | 类型 | 说明 |
|---|---|---|
key |
u8 | DEV_F_*(制造商/位置/容量/MAC/链路/硬件 ID/状态/问题代码/内存范围/I/O 范围/IRQ/…) |
group |
u8 | 事件行号或 BAR 序号(同一键多值时区分) |
value |
char[56] | UTF-8 值,过长截断 |
分页范式沿用 sysinfo_list_t:total 是整表/整 tab 数量,index 是起始项,
n 是本次实际返回;客户端 index += n 直到到顶。
4. 主窗口
客户区 820×540,标题"设备管理器",10 px 圆角 + 柔影,浅色主体。
- 菜单栏(22 px):文件(F) / 操作(A) / 查看(V) / 帮助(H),点击展开浅色浮层。
- 工具栏(36 px):图标按钮组(刷新 / 属性 / 展开全部 / 折叠全部 / 显示隐藏的 设备等),悬停圆角底色、禁用态浅灰线条。
- 设备树(20 px 行高,缩进 14 px/层):可折叠类别 + 设备行;展开箭头
v/>字形; 类别/设备前 12×12 圆角色块(显示蓝、网络青、磁盘灰、USB 紫、未知黄);异常设备行尾 黄色!徽标;选中行为浅蓝底 + 3 px 强调色竖条;悬停高亮。 - 状态栏(24 px):左侧提示"选择设备后按 Enter 查看属性",右侧设备计数;超出时
以
scroll平滑翻页,选中项ensure_visible始终可见。
键盘:↑/↓ 移动选中、Enter 打开属性、F5 刷新(重建设备表并关闭已开属性窗)、
Esc 取消菜单/浮层。
5. 模态属性窗口
客户区 520×600,标题"设备属性",比主窗更高层级,打开时主窗不收输入。
- 选项卡条(44 px):常规 / 驱动程序 / 详细信息 / 事件 / 资源,选中项下划线强调色。
- 常规:24×24 类别图标 + 设备全名;三行键值对(设备类型/制造商/位置);下方 "设备状态"边框圆角文本框(多行状态文字,如"该设备的驱动程序未被安装。(代码 28)")。
- 驱动程序:四行键值对(提供商/日期/版本/数字签名);五个 220×30 竖排操作按钮 (更新/回退/禁用/卸载/属性),禁用项降灰;右侧说明文字。
- 详细信息:属性(P) 下拉框(展开为白色高亮列表,键盘/滚轮可选)+ 值框。
- 事件:时间戳/描述表头 + 3 行表格 + 等宽信息块 + "查看所有事件(V)…"次要按钮。
- 资源:资源类型/设置表格(内存范围 ×2、I/O 范围、IRQ)+ "使用自动设置"勾选 + "更改设置(C)…"禁用按钮 + "冲突设备列表:没有冲突。"。
- 底部:右对齐"确定 / 取消",确定为主按钮(强调色)。
只读边界:更新/回退/禁用/卸载等破坏性操作不做真实驱动变更,点击后仅在对话框内 显示说明行,界面完整、系统不损坏。
6. 窗口管理器支撑
nwm_proto.h:每窗显示列表NWM_MAX_SHAPES 120、NWM_MAX_TEXTS 160(主窗 ≈35/30、属性窗 ≈60/70 图元,只在交互时重绘);NWM_MAX_WINDOWS 10。NWM_F_CREATE_MODAL:模态窗存在时命中测试/键盘只服务该窗、raise不能盖过它、 标题栏只画关闭按钮。apps/src/wm.rs:create_ex(..., flags)与next_event_any() -> (win, Ev)把事件 按窗口 id 路由到主窗或属性窗;其它应用的事件循环不变。
7. 主题与双语
全部界面由 WM 图元(圆角填充/描边/文本)绘制,图标为程序化色块字形,不使用位图。
颜色随系统浅/深色与强调色联动(ui::init / ui::poll 监听主题版本);标签中英双语
(ui::l(zh, en) 内联,未走 lang 字典)。
8. 构建与验证
make一并产出out/NOVUS.EFI与out/apps/devmgmt.bin。- 启动日志
[DEVTAB] n nodes, m pci devices确认设备表建立;WM 运行期若单帧图元超预算 会打印[APP] display list over shape/text budget(正常情况下不应出现)。 - 注册链路:
MakefileAPPS_NAMES→kernel/apps.c应用表 →kernel/session.c白名单 →graphics/nd_demo.c(桌面/任务栏/开始菜单/图标NG_ICON_DEVICES)→apps/src/shell/cmds.rsKNOWN_APPS→apps/Cargo.toml[[bin]]。
NKM 内核模块二进制格式规范 V1.0
NKM 内核模块二进制格式规范
文档版本:V1.0(对应 Novus OS V1.6-FinalSpec) 适用对象:NKM 加载器开发者、驱动开发者、模块签名工具链开发者 平台:x86_64 UEFI 状态:格式冻结;哈希/签名规则已修复并固化,不得变更
1. 概述
NKM(Novus Kernel Module)是 Novus OS 的内核动态模块格式,扩展名 .nkm。
用途:驱动、文件系统扩展、Win32 兼容层、GPU DRM 驱动等可加载组件。
与 NUC(用户态程序)的本质区别:
| 维度 | NUC(用户态) | NKM(内核模块) |
|---|---|---|
| 加载位置 | 用户虚拟地址空间 | 内核地址空间 |
| 权限 | 用户态页表,Ring3 | 内核页表,Ring0 |
| 签名 | 无要求 | 必须 Ed25519 签名 |
| 入口 | entry_point 用户函数 |
nkm_init() + nkm_exit() 双入口 |
| 卸载 | 进程退出自动回收 | 需 nkm_unload 显式调用 |
| 访问范围 | 仅自己地址空间 | 可访问全部内核符号 |
2. 文件整体布局
偏移 0x0000 ┌──────────────────────────────┐
│ NKM Header (nkm_hdr_t) │ 固定 208 字节
偏移 0x00D0 ├──────────────────────────────┤
│ Module Dependencies │ dep_count × nkm_dep_t (16B/条)
偏移 ... ├──────────────────────────────┤
│ Segment Table │ seg_count × nkm_segment_t (32B/条)
偏移 ... ├──────────────────────────────┤
│ Symbol Table │ sym_count × nkm_sym_t (24B/条)
偏移 ... ├──────────────────────────────┤
│ Relocation Table │ rel_count × nkm_rel_t (16B/条)
偏移 ... ├──────────────────────────────┤
│ String Table │
偏移 ... ├──────────────────────────────┤
│ 段数据(.text/.data/.rodata)│ 4KiB 对齐
└──────────────────────────────┘
3. NKM Header(文件头)
固定长度 208 字节(0x00D0),位于文件偏移 0x0000,packed。
修订说明:本节原文写作「128 字节」,与 3.2 的字段偏移表矛盾——表中
reserved[32]位于0xB0,加 32 字节后头部实际结束于0xD0;6.3 的 摘要规则(清零0x50..0xB0)也只在 208 字节布局下成立。现按偏移表 统一为 208 字节,3.2 字段定义与 3.3 类型编号均未改动。
3.1 结构体定义
#define NKM_MAGIC 0x4E4B4D21 // "NKM!"
typedef struct __attribute__((packed)) {
uint8_t magic[4]; // 0x00 "NKM!" = 4E 4B 4D 21
uint16_t abi_version; // 0x04 bit[0..7]=minor, bit[8..15]=major
uint16_t header_size; // 0x06 = 208 (0xD0),便于扩展
uint64_t min_kernel_ver; // 0x08 最低兼容内核版本
uint32_t module_type; // 0x10 模块类型(驱动/FS/兼容层...)
uint16_t seg_count; // 0x14 段数量
uint16_t dep_count; // 0x16 依赖模块数量
uint32_t symtab_count; // 0x18 符号数量
uint32_t rel_count; // 0x1C 重定位数量
uint32_t strtab_offset; // 0x20 字符串表偏移
uint32_t rel_offset; // 0x24 重定位表偏移
uint32_t init_offset; // 0x28 nkm_init() 在 .text 内偏移
uint32_t exit_offset; // 0x2C nkm_exit() 在 .text 内偏移
uint8_t module_name[32]; // 0x30 模块名('\0' 结尾)
uint8_t module_hash[32]; // 0x50 模块本体 SHA256(签名校验字段)
uint8_t module_sig[64]; // 0x70 Ed25519 签名
uint8_t reserved[0x20]; // 0xB0 预留 32 字节
} nkm_hdr_t; // 总大小 208 字节 (0xD0)
3.2 字段逐字节定义
| 偏移 | 大小 | 字段 | 取值规则 |
|---|---|---|---|
| 0x00 | 4 | magic | 固定 NKM!,不匹配拒绝加载 |
| 0x04 | 2 | abi_version | 高字节=major,低字节=minor。当前 0x0100 |
| 0x06 | 2 | header_size | 固定 208(0xD0),未来扩展用 |
| 0x08 | 8 | min_kernel_ver | 加载时校验 内核版本 >= min_kernel_ver |
| 0x10 | 4 | module_type | 见 §3.3 |
| 0x14 | 2 | seg_count | 段数,1~16 |
| 0x16 | 2 | dep_count | 依赖模块数,0=无依赖 |
| 0x18 | 4 | symtab_count | 符号数量 |
| 0x1C | 4 | rel_count | 重定位数量 |
| 0x20 | 4 | strtab_offset | 字符串表文件偏移 |
| 0x24 | 4 | rel_offset | 重定位表文件偏移 |
| 0x28 | 4 | init_offset | nkm_init() 在 .text 段内字节偏移 |
| 0x2C | 4 | exit_offset | nkm_exit() 在 .text 段内字节偏移 |
| 0x30 | 32 | module_name | 模块名,\0 结尾,最长 31 字符 |
| 0x50 | 32 | module_hash | 模块本体 SHA256(见 §6) |
| 0x70 | 64 | module_sig | Ed25519 签名(见 §6) |
| 0xB0 | 32 | reserved | 必须全 0 |
3.3 module_type 取值
| 值 | 名称 | 说明 |
|---|---|---|
| 0 | NKM_TYPE_DRIVER |
硬件驱动(VGA/DP/存储/PCI) |
| 1 | NKM_TYPE_FS |
文件系统驱动 |
| 2 | NKM_TYPE_COMPAT |
兼容层(Win32) |
| 3 | NKM_TYPE_CRYPTO |
加密模块 |
| 4 | NKM_TYPE_OTHER |
其他扩展 |
4. 模块依赖表
紧接 Header 之后,共 dep_count 条,每条 16 字节。
typedef struct __attribute__((packed)) {
uint32_t dep_name_off; // 0x00 依赖模块名在 String Table 的偏移
uint64_t min_dep_ver; // 0x04 依赖模块最低版本
uint32_t reserved; // 0x0C 必须为 0
} nkm_dep_t; // 16 字节
加载规则:
- 加载器按依赖表顺序,先加载被依赖的模块;
- 依赖模块未加载 → 自动递归加载;
- 依赖模块版本不满足
min_dep_ver→ 拒绝加载本模块; - 依赖表出现循环依赖 → 拒绝加载,返回
NOVUS_EDEP。
5. 段表 / 符号表 / 重定位表
格式与 NUC 完全一致(见《NUC 二进制格式规范》第 4/5/7 节),差异点:
| 项 | NKM 差异 |
|---|---|
| 段 vaddr | 加载到内核地址空间(高地址区,非用户区) |
| 段权限 | 全部 Ring0,不要求 VM_USER;TEXT 可执行,DATA 可写 |
| 外部符号 | 解析到内核导出符号表(nksym),而非系统 SDK |
| 重定位类型 | 仅 R_X86_64_64(64 位绝对地址),内核模块不使用 PC32 |
内核导出符号示例(nksym 表,由内核 vmlinux 提供):
mm_alloc, mm_free, vm_map, vm_unmap
sched_spawn, sched_exit
vfs_register_fs, vfs_read, vfs_write
hal_display_probe, hal_display_flush
cap_check, log_print, err_report
pci_enumerate, blk_read, blk_write
6. Ed25519 签名与哈希(核心,已冻结)
6.1 密码套件
- 哈希:SHA256
- 签名:Ed25519(RFC 8032)
- 公钥:32 字节
- 签名:64 字节
6.2 内核公钥池
// 编译时固化在内核镜像中,运行时不可写、不可改
static const ed25519_pubkey_t kernel_trusted_keys[4] = {
/* 公钥1 */, /* 公钥2 */, /* 公钥3 */, /* 公钥4 */
};
static const uint8_t trusted_key_count = 1; // 初始仅1把,后续版本追加
- 最多支持 4 把公钥;
- 仅编译时可更新(密钥轮换 = 发新版内核);
- 运行时不接受用户导入公钥;
- 验证时轮询所有公钥,任一通过即合法。
6.3 哈希计算范围(已修复冲突,冻结)
关键规则:SHA256 计算范围 = 整个模块文件,但跳过
module_hash[32]和module_sig[64]两个字段。
具体操作(签名工具与加载器必须一致):
1. 拷贝整个模块文件到内存 temp_buf
2. 将 temp_buf 中偏移 0x50 起共 96 字节(32+64)置 0
—— 即把 module_hash 和 module_sig 两个字段清零
3. computed_hash = SHA256(temp_buf, 文件总长度)
4. 比对 computed_hash 与头部原始 module_hash:
不一致 → 哈希校验失败,拒绝加载
6.4 签名验证流程
1. 计算出 computed_hash(同 §6.3)
2. 比对 computed_hash == nkm_hdr.module_hash
3. 取头部 module_sig(64 字节)作为 Ed25519 签名
4. 取 nkm_hdr.module_hash(32 字节)作为签名原文
5. 遍历 kernel_trusted_keys[]:
if ed25519_verify(module_hash, module_sig, pubkey[i]):
→ 校验通过,跳出
6. 全部公钥校验失败 → 拒绝加载
6.5 为什么跳过 hash+sig 字段
如果哈希包含自身签名,会造成"鸡生蛋"问题:签名依赖哈希,哈希依赖签名字节。 置零后计算哈希,使哈希与签名解耦:哈希覆盖"除自描述字段外的全部内容",签名再对这个哈希做签名。
7. 模块入口函数约定
每个 NKM 模块必须导出两个函数,通过 init_offset / exit_offset 指向:
// 模块初始化(加载时调用一次)
// 返回 0 成功,负数错误码
int nkm_init(void);
// 模块卸载(卸载时调用一次)
// 返回 0 成功
int nkm_exit(void);
调用约定:
- 与系统调用 ABI 一致(x86_64 SysV);
nkm_init返回非 0 → 加载失败,已分配资源自动回滚;nkm_exit必须释放所有申请的内核资源(内存、IRQ、设备注册),否则卸载后系统状态不一致。
8. 加载完整流程(冻结)
1. nkm_load(path) 被调用
2. 校验调用者 cap_check(mod.load),无权限 → NOVUS_EPERM
3. VFS 打开文件,读取前 208 字节(Header)
4. 校验 magic == "NKM!"
5. 校验 abi_version 主版本号
6. 校验 min_kernel_ver <= 当前内核版本
7. 拷贝整个文件到内核内存
8. 执行哈希校验:
a. 临时副本中 0x50..0xB0 置 0
b. 计算 SHA256
c. 与 module_hash 比对
失败 → NOVUS_ECORRUPT
9. 执行 Ed25519 签名校验(轮询公钥池)
失败 → NOVUS_EMODULE
(管理员单次临时放行:跳过第 9 步,打警告日志)
10. 按依赖表递归加载依赖模块
11. 映射段到内核地址空间
12. 解析重定位(外部符号查内核 nksym 表)
13. 调用 nkm_init()
14. init 返回 0 → 注册到模块列表,返回成功
15. init 失败 → 回滚段映射,返回错误
9. 卸载流程
1. nkm_unload(name) 被调用
2. 校验 cap_check(mod.unload)
3. 检查模块是否被其他模块依赖(dep_count 反向引用)
被依赖 → 拒绝卸载,NOVUS_EBUSY
4. 调用 nkm_exit()
5. 解除段映射
6. 从模块列表移除
7. 释放模块内存
10. 管理员临时放行策略
- 普通用户:未签名模块一律拒绝加载;
- 管理员(拥有
mod.loadCAP):可加载未签名模块,但:- 必须在加载时显式传入
NKM_FLAG_ALLOW_UNSIGNED; - 内核打印 WARNING 日志,记录模块名、PID、时间;
- 仅本次会话有效,不持久保存信任;
- 重启后该模块不会自动加载。
- 必须在加载时显式传入
11. 错误码
| 错误码 | 含义 |
|---|---|
NOVUS_OK (0) |
加载成功 |
NOVUS_EPERM (-4) |
无 mod.load / mod.unload CAP |
NOVUS_EINVAL (-1) |
头部字段非法 |
NOVUS_ECORRUPT (-7) |
SHA256 哈希不匹配 |
NOVUS_EMODULE (-8) |
Ed25519 签名验证失败 |
NOVUS_EBUSY (-5) |
模块被依赖,无法卸载 |
NOVUS_ENOTFOUND (-3) |
依赖模块缺失 |
NOVUS_EDEP (-12) |
循环依赖 |
NOVUS_EIO (-6) |
文件读取失败 |
NOVUS_ENOMEM (-2) |
内核内存不足 |
12. 完整示例:一个最小驱动模块
12.1 Header 关键字段
magic: 4E 4B 4D 21 ("NKM!")
abi_version: 00 01 (major=1, minor=0)
header_size: D0 00 (208)
min_kernel_ver: 00 00 00 00 00 00 00 01 (要求内核 >= 1.0)
module_type: 00 00 00 00 (DRIVER)
seg_count: 02 00 (2段)
dep_count: 00 00 (无依赖)
symtab_count: 01 00 00 00
rel_count: 02 00 00 00
strtab_offset: 00 02 00 00 (0x200)
rel_offset: C0 01 00 00 (0x1C0)
init_offset: 10 00 00 00 (.text+0x10)
exit_offset: 30 00 00 00 (.text+0x30)
module_name: "nvme.ko" 00 00...
module_hash: <32字节SHA256>
module_sig: <64字节Ed25519签名>
12.2 模块源码骨架(C)
#include <novus/nkm.h>
#include <novus/mm.h>
#include <novus/log.h>
static void* buf = NULL;
int nkm_init(void)
{
log_print(LOG_INFO, "nvme driver init\n");
buf = mm_alloc(1);
if (!buf) return NOVUS_ENOMEM;
// 注册 NVMe 控制器
return NOVUS_OK;
}
int nkm_exit(void)
{
log_print(LOG_INFO, "nvme driver exit\n");
if (buf) mm_free(buf, 1);
return NOVUS_OK;
}
NUC 与 NKM 是不同格式:cppcc 只生成用户态 .nuc,不参与 NKM 目标文件编译或签名。
当前仓库的 tools/nkmgen 是主机端 NKM 测试镜像生成器,复用内核 Ed25519/SHA 实现生成并签名测试模块;它不是通用 C/C++ NKM 编译器。通用驱动目标文件到 NKM 的生产工具链不属于 cppcc。
13. 文档冻结声明
本规范为 NKM 内核模块格式唯一基准文档。约束:
- Header 208 字节布局(0x00D0),含 reserved[32];
- 哈希跳过 0x50..0xB0(hash+sig 字段)后计算 SHA256;
- Ed25519 签名原文 =
module_hash(32 字节); - 内核公钥池最多 4 把,编译时固化;
- 入口固定
nkm_init/nkm_exit; - 依赖表递归加载,禁止循环依赖。
任何变更必须走 ABI 变更 RFC,升版本号。
文档状态: 可作为 M3(NKM 加载器)与 M10(驱动生态)的实现基准。
Novus OS Debug 级接口手册 V1.0
Novus OS Debug 级接口手册
文档版本:V1.0(对应 Novus OS V1.6-FinalSpec) 用途:开发调试手册,每个接口展开到参数级、错误码级、前置/后置条件、调试检查点 配套:《全部接口总表》《NUC 格式规范》《NKM 格式规范》 状态:冻结
0. 阅读指南
每个接口条目包含:
- 原型:C 函数签名
- 所属子系统
- 调用方 / 被调用方
- 前置条件:调用前必须满足什么(锁、CAP、中断状态、内存)
- 参数表:逐字段类型、取值范围、单位、默认值、说明
- 返回值:逐情况说明
- 错误码对照表:什么情况返回什么错误码
- 后置条件:返回后系统状态变化
- 调试检查点:开发时应该打日志/断言的位置
- 使用示例:最小调用代码
- 常见 Bug:易犯错误
1. 通用错误码(全局复用)
| 值 | 宏名 | 含义 | 触发场景举例 |
|---|---|---|---|
| 0 | NOVUS_OK | 成功 | 一切正常 |
| -1 | NOVUS_EINVAL | 参数无效 | 指针为NULL、长度为0、枚举值越界 |
| -2 | NOVUS_ENOMEM | 内存不足 | 页分配失败、缓冲区不够 |
| -3 | NOVUS_ENOTFOUND | 对象不存在 | 路径不存在、符号未找到、设备不存在 |
| -4 | NOVUS_EPERM | 权限不足 | cap_check() 返回 false |
| -5 | NOVUS_EBUSY | 资源忙 | 锁超时、文件被占用、模块被依赖 |
| -6 | NOVUS_EIO | IO错误 | 磁盘读失败、PCI读写错误 |
| -7 | NOVUS_ECORRUPT | 数据损坏 | SHA256不匹配、CRC32校验失败 |
| -8 | NOVUS_EMODULE | 模块错误 | 签名校验失败、ABI不兼容 |
| -9 | NOVUS_EFULL | 队列满 | IPC队列满、WAL日志满 |
| -10 | NOVUS_EAGAIN | 重试 | 资源暂时不可用 |
| -11 | NOVUS_EOVERFLOW | 溢出 | 段大小越界、文件偏移超出文件长度 |
| -12 | NOVUS_EDEP | 循环依赖 | 模块依赖图成环 |
2. SMP / AB 双核接口
2.1 smp_shmem_write
void smp_shmem_write(uint32_t offset, uint64_t val);
- 所属:SMP 启动
- 调用方:A核(BSP)
- 前置条件:
- 共享内存物理页已预留(A核早期分配)
- 调用者已持有
smp_shmem_lock()(如多核心并发写) - 本地中断状态:允许开中断
- 参数:
| 参数 | 类型 | 范围 | 说明 |
|---|---|---|---|
| offset | uint32_t | 0 ~ 4095 | 共享内存内偏移,必须 8 字节对齐 |
| val | uint64_t | 任意 | 要写入的值 |
- 返回值:无(void)
- 后置条件:共享内存指定偏移处值更新;CPU 缓存一致性由
sfence保证 - 调试检查点:
- 写入后立即读回比对:
assert(smp_shmem_read(offset) == val); - 打印:
log_print(DEBUG, "shmem write off=%u val=%lx\n", offset, val);
- 写入后立即读回比对:
- 常见 Bug:offset 未对齐导致原子性破坏;忘记持锁导致竞态
2.2 smp_shmem_read
uint64_t smp_shmem_read(uint32_t offset);
- 调用方:B核(AP)
- 前置条件:共享内存已映射到 AP 页表
- 参数:offset 同上
- 返回值:指定偏移处的值
- 调试检查点:读取
bsp_state时循环等待,超时 200ms 判定启动失败
2.3 smp_shmem_lock / smp_shmem_unlock
int smp_shmem_lock(void);
void smp_shmem_unlock(void);
- 锁类型:自旋锁
- 自旋上限:1,000,000 次
- 超时返回:
NOVUS_EBUSY (-5) - 调试检查点:
- 加锁前后打日志
- 超时触发时打印当前锁持有者信息(如实现了锁调试)
- 注意:锁内禁止调用可能睡眠的函数(此时调度器未启动)
2.4 acore_enter_sleep
void acore_enter_sleep(void);
- 调用方:A核自检完成后
- 前置条件:
- 所有硬件信息已写入共享内存
- IPI 已发送给所有 AP
bsp_state已置 2
- 行为:进入
cli; hlt;无限循环 - 后置条件:BSP 不再执行任何指令
- 调试检查点:进入前打印 "Acore entering sleep"
2.5 smp_wake_ap
int smp_wake_ap(uint64_t ap_id);
- 前置条件:
bsp_state已置 2- 已执行
sfence - AP 启动栈地址已写入共享内存
- 参数:ap_id = AP 核心编号
- 行为:发送 IPI 向量 0x80
- 返回值:0 成功;-ENOMEM 失败
- 调试检查点:发送后等待
ap_ready标志,超时 200ms → 重启
2.6 smp_ap_signal_ready
void smp_ap_signal_ready(void);
- 调用方:AP 完成 GDT/IDT/页表初始化后
- 后置条件:共享内存
ap_ready = 1;BSP 检测到后休眠
3. 内存管理接口
3.1 mm_alloc
void* mm_alloc(size_t pages);
- 所属:物理内存管理
- 前置条件:
- 物理内存管理器已初始化(M1 之后)
- 调用者不在中断上下文(或使用 GFP_ATOMIC 标志)
- 参数:
| 参数 | 类型 | 单位 | 说明 |
|---|---|---|---|
| pages | size_t | 4KiB/页 | 要分配的连续物理页数 |
- 返回值:
- 成功:内核虚拟地址(已映射)
- 失败:
NULL
- 错误码:返回 NULL 即失败(不通过返回值传错码)
- 后置条件:
- 物理页已保留(从空闲位图标记为已占用)
- 已映射到内核虚拟地址空间
- 调试检查点:
- 分配后打印:
log_print(DEBUG, "mm_alloc %zu pages -> %p\n", pages, ptr); - 检查返回值是否对齐:
assert((uint64_t)ptr % 4096 == 0);
- 分配后打印:
- 常见 Bug:
- pages=0 直接 panic
- 分配后忘记
mm_free→ 内存泄漏 - 在中断上下文调用可睡眠版本 → 死锁
3.2 mm_free
void mm_free(void* vaddr, size_t pages);
- 参数:
- vaddr:
mm_alloc返回的地址 - pages:必须与分配时一致
- vaddr:
- 后置条件:物理页归还空闲位图;虚拟映射解除
- 调试检查点:释放后打印地址;检查双重释放(位图标记)
3.3 vm_map
int vm_map(uint64_t va, uint64_t pa, uint64_t len, uint32_t flags);
- 参数:
| 参数 | 类型 | 单位 | 说明 |
|---|---|---|---|
| va | uint64_t | 字节 | 虚拟起始地址,4KiB 对齐 |
| pa | uint64_t | 字节 | 物理起始地址,4KiB 对齐 |
| len | uint64_t | 字节 | 长度,4KiB 对齐 |
| flags | uint32_t | 位掩码 | bit0=READ bit1=WRITE bit2=EXEC bit3=USER |
- 返回值:0 成功;负数错误码
- 错误码:
- -EINVAL:va/pa/len 未对齐
- -ENOMEM:页表分配失败
- 调试检查点:映射后读 CR3 验证 TLB;打印映射范围
- W^X 原则:flags 同时置 WRITE 和 EXEC → 拒绝(返回 -EINVAL)
3.4 vm_unmap
int vm_unmap(uint64_t va, uint64_t len);
- 解除映射,释放页表项
- 后置条件:访问该地址触发页错误
3.5 oom_scan
int oom_scan(proc_info_t* out);
- 前置条件:内存水位 < 10%
- 行为:遍历所有进程,按评分公式计算分数
- 评分公式(冻结):
score = rss_bytes * front_weight * age_weight * type_weight front_weight: 前台=1.8, 后台=1.0 age_weight: <30s=1.0, 30s~5min=0.7, >5min=0.4 type_weight: 普通=1.0, 系统辅助=0.2 - 保护列表(永不参与评分):init、novus-wm、novus-settings、novus-taskmgr
- 返回值:0 找到候选进程,写入 out;-ENOMEM 无候选进程可杀
- 调试检查点:
- 打印每个进程的 score
- 打印选中的 victim
- 常见 Bug:误杀保护列表进程 → 系统崩溃
3.6 oom_reclaim
int oom_reclaim(uint32_t level);
- 参数:level
- 0 = 温和:只回收页缓存、目录项缓存
- 1 = 紧急:回收离屏 FB、NovusFS 冗余缓存
- 回收顺序(冻结):文件页缓存 → 目录项缓存 → 图形离屏缓冲 → NovusFS 缓存
- 防抖:1 秒内最多触发一次全局回收
4. 调度器接口
4.1 sched_spawn
int sched_spawn(const char* path, uint64_t caps, pid_t* out_pid);
- 前置条件:
- 调用者拥有
sys.proc.ctrlCAP(创建系统进程) - path 指向的 .nuc 文件存在
- 调用者拥有
- 参数:
| 参数 | 说明 |
|---|---|
| path | .nuc 文件路径,如 "/system/bin/novus-settings" |
| caps | 进程初始 CAP 掩码(低64位) |
| out_pid | 输出参数,成功写入新 PID |
- 返回值:0 成功;负数错误码
- 错误码:
- -ENOENT:文件不存在
- -EINVAL:.nuc 头部校验失败
- -ENOMEM:无法分配进程地址空间
- 调试检查点:打印新进程 PID、入口地址、初始栈
- 后置条件:进程加入就绪队列,等待调度
4.2 sched_ctl
int sched_ctl(pid_t pid, uint32_t op, void* arg);
- 参数 op:
- 0 = 暂停进程(SIGSTOP)
- 1 = 恢复进程(SIGCONT)
- 2 = 终止进程(SIGKILL)
- 3 = 调试 attach
- CAP:
sys.proc.ctrl - 调试检查点:打印 pid、op、返回值
4.3 sched_exception_report
int sched_exception_report(pid_t pid, exc_info_t* exc);
- 触发时机:用户态进程触发页错误/非法指令/除零
- 行为:
- 收集寄存器状态到 exc_info_t
- 不 panic,不杀进程
- 通过 IPC 发消息给 novus-wm
- WM 弹出错误对话框
- exc_info_t 字段:
typedef struct {
uint64_t pid;
uint64_t rip; // 出错指令地址
uint64_t cr2; // 页错误地址
uint32_t err_code; // 错误码
char proc_name[64];
uint8_t cause; // 0=页错误 1=非法指令 2=除零 3=断点
} exc_info_t;
5. 安全/CAP 接口
5.1 cap_check
int cap_check(proc_cap_t* p, uint32_t bit);
- 参数:
- p:进程的 CAP 结构指针
- bit:要检查的位号(0~31)
- 返回值:
- 1:拥有该权限
- 0:没有该权限
- 实现:
return (p->cap_mask_low >> bit) & 1; - 调试检查点:权限拒绝时打印进程名、请求的 bit 号
- 常见 Bug:bit 号写错(off-by-one);忘记检查导致越权
5.2 cap_drop
int cap_drop(proc_cap_t* p, uint32_t bit);
- 行为:清除指定位(不可逆)
- 用途:进程初始化完成后主动降权(最小权限)
- 返回值:0 成功;-EINVAL bit 越界
5.3 nkm_load
int nkm_load(const char* path);
- 前置条件:调用者拥有
mod.loadCAP - 执行步骤(debug 级):
- 打开文件,读前 128 字节 Header
- 校验 magic == "NKM!" → 失败返回 -ENOENT
- 校验 abi_version 主版本 == 1 → 否则 -EINVAL
- 校验 min_kernel_ver <= 当前内核版本 → 否则 -EMODULE
- 拷贝整个文件到内核内存
- 哈希校验:
- 临时副本中偏移 0x50 起 96 字节置 0
- 计算 SHA256
- 与头部 module_hash 比对 → 不匹配 -ECORRUPT
- 签名校验:
- 遍历 kernel_trusted_keys[0..key_count-1]
- 对 module_hash 做 Ed25519 verify
- 全部失败 → -EMODULE
- (管理员放行:传 NKM_FLAG_ALLOW_UNSIGNED 跳过此步)
- 递归加载依赖
- 映射段到内核地址空间
- 应用重定位
- 调用 nkm_init() → 非0返回则回滚
- 调试检查点:每一步打日志,失败时打印具体步骤
- 常见 Bug:
- 哈希计算时忘记置零 hash+sig 字段 → 永远不匹配
- 重定位时外部符号没找到 → 内核 oops
6. VFS 接口
6.1 vfs_open
int vfs_open(const char* path, uint32_t flags, uint32_t mode);
- 参数 flags:
- bit0 = O_RDONLY
- bit1 = O_WRONLY
- bit2 = O_RDWR
- bit3 = O_CREAT
- bit4 = O_TRUNC
- 路径检查:
/system下写操作需要fs.fullCAP- 路径解析失败 → -ENOENT
- 返回值:文件描述符(正整数);负数错误码
- 调试检查点:打印 path、flags、返回的 fd
6.2 vfs_read / vfs_write
int vfs_read(int fd, void* buf, uint64_t len);
int vfs_write(int fd, const void* buf, uint64_t len);
- 参数:
- fd:vfs_open 返回的描述符
- buf:缓冲区指针
- len:要读/写的字节数
- 返回值:实际读/写字节数;负数错误码
- 调试检查点:打印 fd、len、实际传输量
- 常见 Bug:buf 为 NULL;fd 越界;文件指针未推进
7. NovusFS 接口
7.1 novusfs_alloc_block
int novusfs_alloc_block(uint64_t* out_block);
- 前置条件:持有块分配器锁
- 行为:扫描块位图找第一个空闲位
- 返回值:0 成功,*out_block 填入块号
- 错误码:
- -ENOSPC:磁盘满
- -ECORRUPT:位图标记了坏块但块号仍被分配
- 调试检查点:打印分配的块号;验证位图已置 1
- 锁顺序:超级块锁 → 目录锁 → inode锁 → 块分配器锁(最内层)
7.2 WAL 事务
wal_begin_tx
int wal_begin_tx(uint32_t type, uint64_t block_no, wal_tx_t* out);
- type:0=块写 1=inode修改 2=目录修改
- 写入 PREP 记录到 WAL 区
- 返回 0 成功;-EFULL 日志区满
wal_commit
int wal_commit(wal_tx_t* tx, const void* data, uint32_t len);
- 写数据 + COMMIT 记录
- 后置:事务持久化
wal_rollback
void wal_rollback(wal_tx_t* tx);
- 丢弃 PREP 记录(不写 COMMIT)
WAL 满判定
// 满条件:write_ptr == tail_ptr
if (wal_write_ptr == wal_tail_ptr) {
// 推进 tail 到下一个完整事务边界
wal_advance_tail();
}
8. Merkle 树接口
8.1 merkle_verify_root
int merkle_verify_root(dev_t dev, const uint8_t expect[32]);
- 调用方:A核开机自检
- 行为:
- 读取超级块中的 merkle_root_primary
- 如果 primary 损坏,读 backup
- 比对 expect(A核自己计算的哈希)与存储的根
- 不一致 → 返回 -ECORRUPT
- 错误码:
- -ECORRUPT:哈希不匹配
- -EIO:磁盘读失败
- 调试检查点:打印 expect 和 stored 两个哈希的前 8 字节
8.2 节点磁盘映射
// idx: 节点索引(根=1)
uint64_t node_to_block(uint64_t idx) {
return merkle_start_block + (idx / 64);
}
uint64_t node_offset_in_block(uint64_t idx) {
return (idx % 64) * 64;
}
- 边界检查:
- leaf_count == 0 → 拒绝挂载
- leaf_count == 1 → 树高=2,根=1,叶子起始=2
9. 图形栈系统调用
9.1 sys_gfx_create_surface
int sys_gfx_create_surface(uint32_t w, uint32_t h, uint32_t fmt, fb_handle_t* out);
- 参数:
- w/h:宽高(像素)
- fmt:0=BGRA8888, 1=BGR24
- out:输出帧缓冲句柄
- LowMem 限制:最多 4 个离屏 FB
- Full 限制:最多 16 个
- 调试检查点:打印 w、h、分配的 fb 地址
- 错误码:-ENOMEM 分配失败
9.2 sys_gfx_submit_dirty
int sys_gfx_submit_dirty(fb_handle_t h, const rect_t* rects, uint32_t n);
- 参数 rect_t:
typedef struct { uint32_t x, y, w, h; } rect_t; - 限制:n 最大 8(Full)/ 4(LowMem)
- 行为:标记窗口脏区域,触发合成器重绘
- 调试检查点:打印 rect 数量和坐标
10. IPC 接口
10.1 ipc_send
int ipc_send(novus_ipc_hdr_t* hdr, const void* payload);
- 前置条件:
- 调用者已通过
ipc_bind注册通道 - 拥有对应窗口的归属权(或 gui.override CAP)
- 调用者已通过
- hdr 必须字段:
- magic = 0x4E574D49
- sender_pid = 当前进程 PID
- msg_type = 有效消息类型
- payload_len = 实际 payload 长度
- 错误码:
- -EFULL:目标队列满
- -EINVAL:magic 错误
- -EPERM:无权限
- 调试检查点:打印 msg_type、target_pid、payload_len
11. 系统调用 ABI(debug 要点)
11.1 寄存器约定
| 用途 | 寄存器 |
|---|---|
| 调用号 | rax |
| 参数1 | rdi |
| 参数2 | rsi |
| 参数3 | rdx |
| 参数4 | rcx |
| 参数5 | r8 |
| 参数6 | r9 |
| 返回值 | rax |
| 被调用者保存 | rbp, rbx, r12, r13, r14, r15 |
11.2 常见调试技巧
- 系统调用号打印:在 syscall 入口打印 rax 和参数
- 返回值检查:用户态库包装后检查 rax 是否为负
- 栈对齐:进入内核时检查 rsp % 16 == 0
- 权限拒绝:syscall 入口先 cap_check,拒绝时打印 bit 号
12. 日志接口
12.1 log_print
void log_print(uint32_t level, const char* fmt, ...);
- level:
- 0 = DEBUG(开发调试)
- 1 = INFO(正常信息)
- 2 = WARN(警告)
- 3 = ERROR(错误)
- 行为:写入环形缓冲区 + 串口输出
- LowMem:DEBUG 级别不输出(节省串口带宽)
- 调试检查点:模块初始化函数开头打 INFO
12.2 panic_handler
void panic_handler(cpu_state_t* state);
- 触发时机:内核致命错误(双重缺页、致命锁死)
- 行为:
- 关中断
- VGA 文本模式打印寄存器转储
- HLT 死循环
- 绝不返回。用户态进程崩溃走
sched_exception_report,不走 panic。
13. 调试通用建议
13.1 打印策略
- 模块 init:打 INFO
- 关键错误:打 ERROR + 错误码
- 调试细节:打 DEBUG(LowMem 关闭)
- 不要在中断高频路径打日志(VSync 每帧)
13.2 断言
- 指针非 NULL:
assert(ptr != NULL); - 对齐:
assert((uint64_t)addr % 16 == 0); - 锁持有:调试时可记录当前锁持有者
- 返回值:
int ret = foo(); assert(ret == NOVUS_OK);
13.3 常见 Bug 清单
- 忘记持锁 → 多进程竞态
- 锁顺序错误 → 死锁(必须按 超级块→目录→inode→块分配)
- 双重释放 → 内存 corruption
- 偏移未对齐 → x86_64 严格对齐异常
- CAP 忘记检查 → 越权访问
- WAL 写了 PREP 没写 COMMIT → 崩溃后数据丢失
- Merkle 哈希包含了自身 hash 字段 → 校验永远失败
- NKM 签名时公钥不匹配 → 模块无法加载
文档状态
本文档为 Debug 级接口手册,开发时对照此文档逐行检查代码。 所有函数签名、参数、错误码、前置条件已冻结。
文档状态:✅ 冻结,可作为 M0–M10 开发调试基准。
Novus OS 自研分级增量更新体系完整规范
1. Novus OS 自研更新架构核心体系
Novus OS 搭载完全自研、独立可控、工业级稳定的分类补丁、分级推送、分通道灰度、断点续传、事务原子回滚、服务端统一管控更新体系,专为自研操作系统量身设计,架构轻量化、逻辑透明、可手动调试、可全自动批量部署,为系统长期迭代、安全风控、软件运维提供标准化底层支撑。
1.1 Novus OS 三大官方补丁体系(永久冻结)
-
.hotpth 紧急安全热修复补丁:专注高危漏洞、远程代码执行、内核提权、权限绕过等安全风险紧急兜底修复,最高系统优先级,强制静默更新
-
.npth 系统通用累积补丁:负责系统内核、NKM驱动、HAL层、系统基础库、核心服务的常规累积迭代、稳定性优化与功能迭代
-
.apth 应用软件专属补丁:面向NUC应用、第三方软件、桌面组件、用户工具的独立增量更新,隔离系统核心层与用户应用层更新逻辑
-
.novu 全量安装包:承接系统大版本跨代升级、首次装机、系统重置重装场景,作为增量补丁的底层兜底载体(替代已占用NUP格式,为全新自研专属后缀)
1.2 Novus OS 五级官方更新推送通道(永久冻结)
系统内置自研五级更新分级机制,覆盖从紧急安全修复、稳定版本推送、灰度功能预览、普通可选更新、开发者内测更新全场景,分级策略独立、权限隔离、互不干扰,适配普通用户、进阶用户、开发者、企业批量运维全群体需求:
-
紧急安全推送(level_urgent):专属安全漏洞热修复,系统最高优先级,无拦截、无延后、强制即时修复
-
稳定推荐推送(level_recommend):系统与软件稳定版迭代更新,默认推荐安装,保障设备稳定性与兼容性
-
版本预览推送(level_preview):新功能灰度尝鲜版本,仅主动查询可见,无被动弹窗推送
-
普通可选推送(level_optional):非必要体验优化、辅助功能迭代,用户自主选择安装或忽略
-
开发者内测推送(level_dev):开发调试版、未稳定内测版本,默认隐藏,仅开发者模式解锁可见
2. Novus OS 自研更新核心机制与技术规范
2.1 服务端核心:全局唯一统一更新大表架构
Novus OS 远程更新服务端采用自研单全局唯一更新索引大表架构,为所有终端设备更新的唯一权威数据源,摒弃分散分表的复杂设计,架构极简、检索高效、运维便捷。
核心运行逻辑:
-
服务端统一收录全部 .npth/.apth/.hotpth 格式补丁数据,集中管控所有版本、灰度、策略信息
-
客户端后台常驻定时轮回查询大表,静默完成版本比对与补丁匹配
-
所有复杂逻辑(版本适配、分级筛选、灰度命中、策略判定)由服务端统一完成
-
客户端仅负责下载、校验、执行更新,逻辑轻量化,降低系统资源占用与故障概率
2.2 客户端核心:分层优先级更新队列机制(冻结)
系统内置固定优先级更新队列,多补丁同时存在时,严格按照既定优先级串行执行,避免更新冲突、资源抢占、版本错乱问题。
更新执行优先级(从高至低,永久冻结):
.hotpth 紧急安全热修复 > .npth 系统累积更新 > .apth 关键软件更新 > 预览版灰度更新 > 普通可选更新 > Dev开发者内测更新
2.3 自研事务性原子更新与智能回滚机制
-
更新前置自动快照备份系统关键文件、权限配置、版本信息,留存完整回滚镜像
-
针对更新中断、设备断电、文件异常、校验失败等所有异常场景,触发全自动事务回滚
-
严格杜绝半更新状态,保障系统文件完整性与运行稳定性
-
所有更新操作具备事务唯一性,要么全部成功生效,要么完整还原初始状态
2.4 自研差分增量更新与断点续传机制
-
全系补丁默认启用字节级差分增量更新,仅传输文件变更数据块,极大降低远程更新流量开销
-
内置下载进度持久化模块,支持断网、断电、退出中断后无缝接续下载
-
安装阶段支持断点续执行,已完成的差分块、文件操作无需重复执行,提升更新效率
7. Novus OS 更新体系二进制文件头规范(全局冻结|可直接编码)
本节定义 .novu / .npth / .apth / .hotpth 四类更新载体的统一二进制文件头结构。所有结构体强制 packed、4字节对齐、字段偏移永久锁定,用于解析器精准识别文件类型、校验合法性、读取更新策略,杜绝后缀伪造、文件篡改、格式错乱。
核心设计原则:后缀与文件头魔数强绑定、类型字段二次校验、标志位控制行为、全局哈希防篡改、预留位保证向前兼容。
7.1 全局公共定义(全部文件通用|冻结)
// 全局版本冻结
#define NOVUS_UPDATE_HDR_VER_MAJOR 1
#define NOVUS_UPDATE_HDR_VER_MINOR 0
// 文件类型枚举(永久唯一)
#define NOVU_TYPE_FULL 0 // .novu 全量安装包
#define NOVU_TYPE_SYS_PATCH 1 // .npth 系统通用补丁
#define NOVU_TYPE_APP_PATCH 2 // .apth 软件专属补丁
#define NOVU_TYPE_HOT_PATCH 3 // .hotpth 紧急热修复补丁
// 五级更新分级枚举(绑定服务端大表策略)
#define UPDATE_LVL_OPTIONAL 0
#define UPDATE_LVL_RECOMMEND 1
#define UPDATE_LVL_PREVIEW 2
#define UPDATE_LVL_URGENT 3
#define UPDATE_LVL_DEV 4
7.2 四类文件专属魔数(防伪造|一一对应|冻结)
文件头魔数为第一校验依据,后缀仅为系统展示用,解析器以魔数为准,防止手动改后缀伪装补丁。
// 小端内存序、文件存储序统一
#define NOVU_FULL_MAGIC 0x554E5653 // NVUS → .novu
#define NOVU_NPTH_MAGIC 0x50544853 // PTHS → .npth
#define NOVU_APTH_MAGIC 0x41505448 // APTH → .apth
#define NOVU_HOTPTH_MAGIC 0x484F5450 // HOTP → .hotpth
7.3 统一标准文件头结构体(128Byte 固定|四类文件通用)
四类更新文件共用同一套128字节头部布局,仅 magic、file_type、默认 update_level 不同,极大降低解析器代码冗余,同时严格隔离四类载体行为。
typedef struct __attribute__((packed)) {
// 0x00 基础魔数与版本
uint32_t magic; // 四类文件专属魔数
uint16_t ver_major;
uint16_t ver_minor;
// 0x08 文件类型 + 更新分级
uint8_t file_type; // 0=novu 1=npth 2=apth 3=hotpth
uint8_t update_level; // 0~4 对应五级更新通道
uint8_t remote_support; // 1=允许远程下发 0=仅本地手动安装
uint8_t reserved_0;
// 0x0C 全局标志位(位掩码控制更新行为)
uint32_t flag_bits;
// 0x10 版本适配区间
uint64_t target_os_ver; // 目标适配系统版本
uint64_t min_compat_ver; // 最低兼容兜底版本
// 0x20 内容块计数
uint32_t entry_count; // 文件操作项/资源项总数
uint32_t delta_block_count; // 差分块数量(全量包可为0)
// 0x28 各区块文件偏移与长度
uint32_t meta_offset; // 元数据/Manifest 偏移
uint32_t meta_len;
uint32_t table_offset; // 操作表/索引表偏移
uint32_t table_len;
uint32_t data_offset; // 原始数据/差分数据区偏移
uint32_t data_len;
uint32_t snapshot_offset; // 快照回滚哈希表偏移
uint32_t snapshot_len;
// 0x60 全局完整性校验
uint8_t file_sha256[32]; // 整包除签名区外哈希
// 0x80 签名信息
uint32_t sig_offset;
uint32_t sig_len;
// 0x88 补丁唯一ID(16位十六进制ID二进制存储)
uint8_t patch_uuid_bin[8];
// 0x90 预留填充至128字节,向前兼容扩展
uint8_t reserved_fill[24];
} novus_update_header_t;
7.4 全局 Flag 位掩码定义(冻结)
统一位掩码控制各类更新行为,客户端/服务端按位判定策略。
bit0 = 1 开启快照回滚
bit1 = 1 差分增量模式 / 0 全量替换模式
bit2 = 1 支持断点续传
bit3 = 1 支持内核热更新(无需重启)
bit4 = 1 允许覆盖系统只读路径
bit5 = 1 更新后自动刷新桌面/服务
bit6 = 1 远程静默安装模式
bit7 = 1 安全紧急强制兜底模式
bit8~31 保留
7.5 四类文件头部字段差异化绑定规则(永久冻结)
统一结构体 + 差异化固化参数,保证格式统一、行为隔离、层级严谨。
| 文件后缀 | Magic | file_type | 默认 update_level | 核心行为固化 |
|---|---|---|---|---|
| .novu 全量包 | NVUS | 0 | 1(推荐级) | 大版本替换、支持回滚、仅重大迭代使用 |
| .npth 系统补丁 | PTHS | 1 | 1(推荐级) | 系统核心迭代、后台执行、可延后次数管控 |
| .apth 软件补丁 | APTH | 2 | 0(可选级) | 用户态更新、弹窗询问、可永久忽略 |
| .hotpth 热修复 | HOTP | 3 | 3(紧急级) | 最高优先级、静默强制、禁止延后、插队执行 |
7.6 16进制补丁UUID 二进制存储规范
对外文件名:16位大写十六进制字符串
对内文件头:8字节原生二进制存储(16Hex = 64bit)
校验逻辑双向绑定冻结:
-
打包器由SHA256摘要截取前64bit生成唯一ID
-
写入头部
patch_uuid_bin[8] -
同时格式化输出16位大写Hex作为文件名
-
解析器校验:文件名Hex <-> 头部二进制ID 必须一致,不一致直接拒绝安装,判定为非法篡改包
7.7 头部合法性校验流水线(硬件级可靠|冻结流程)
客户端/服务端接收任意更新文件,严格按以下顺序校验,任意一步失败直接丢弃:
-
校验前128字节头部完整性
-
匹配对应魔数,判定真实文件类型
-
校验主次版本兼容
-
校验二进制UUID与文件名一致性
-
校验系统版本适配区间
-
校验全局SHA256完整性
-
校验Ed25519数字签名合法性
-
通过后按 update_level 进入对应更新队列
7.8 区块偏移通用排布规则(四类文件统一)
所有更新文件从偏移0开始排布顺序永久固定:
128B文件头 → Meta元数据区 → 文件操作索引表 → 差分数据表 → 数据正文区 → 快照哈希区 → 签名区
保证解析器线性读取、无需自适应判断,极致降低解析复杂度与BUG率。
3. Novus OS 自研更新体系增强策略规范
基于自研架构迭代优化,新增多项工业级增强策略,完善全场景更新能力,所有扩展规则兼容原有冻结底层结构,无破坏性变更。
3.1 智能空闲时段静默更新策略
为兼顾更新时效性与用户使用体验,自研分时更新调度机制:
-
.hotpth 紧急安全补丁:不受时段限制,即时后台静默修复,优先保障系统安全
-
系统、软件常规更新:自动识别设备空闲、锁屏、夜间低活跃时段,后台静默执行更新
-
支持用户自定义免打扰时段,期间禁止非紧急类更新触发
3.2 更新失败智能重试与设备自愈降级策略
-
单次更新异常失败后,系统自动触发3次梯度重试,重试间隔逐级递增,规避临时环境异常问题
-
多次重试持续失败,自动标记该补丁与当前设备不兼容,服务端自动拉黑停止推送
-
本地自动留存故障日志、更新快照、异常信息,同步上报服务端,形成运维闭环
3.3 设备维度精细化灰度放量机制
服务端统一大表内置完整灰度管控逻辑,支撑版本平稳迭代:
-
支持按设备ID、设备批次、硬件机型、系统版本、用户分组精细化灰度推送
-
支持百分比放量更新,小范围验证稳定后逐步全量铺开,规避批量BUG风险
-
开发者预览、内测版本支持白名单专属推送,仅授权设备可获取更新
3.4 系统后台驻留更新服务(完整后台能力闭环)
Novus OS 更新体系内置系统级常驻后台更新守护服务,独立于前台UI、独立生命周期、低功耗驻留系统内核服务层。所有更新检测、版本比对、下载预载、静默安装、状态同步、撤回预处理全部支持后台无感知运行,支持前台退出、锁屏待机、用户离线状态下持续完成更新全流程。
3.4.1 后台服务核心属性(系统常驻级)
-
内核级守护驻留:更新服务为系统核心自启动服务,开机自动挂载、后台长期常驻、不受前台应用退出影响,无闪退、无后台冻结,保障更新链路持续可用
-
低资源占用调度:后台空闲休眠、轮询时段轻量化唤醒,仅版本比对与增量校验时瞬时占用CPU,常态内存占用极低,不影响整机性能与续航
-
独立任务生命周期:下载、校验、安装、回滚、残留清理均为后台独立任务,前台关闭设置界面、切换用户、锁屏待机不中断任务执行
-
断电续任务:后台所有更新任务状态持久化写入系统更新注册表,重启后自动恢复未完成任务断点,接续执行剩余流程
3.4.2 后台完整可执行能力清单
所有更新核心逻辑完全后台化,无需前台介入:
-
后台静默轮询检测:常驻后台定时轮回查询远程统一大表,自动匹配本机适配补丁、分级筛选更新队列
-
后台静默下载预载:空闲时段后台自动下载差分补丁包,下载完成静默缓存,等待最佳安装时机,实现“开机即用最新版本”
-
后台静默校验鉴权:后台自动完成魔数校验、UUID双向校验、SHA256完整性校验、Ed25519签名校验,非法包后台自动丢弃并日志归档
-
后台静默安装执行:紧急安全补丁、后台许可的稳定补丁可完全后台静默安装,无弹窗、无打扰、无需用户确认
-
后台快照备份预处理:检测到待更新任务时,后台提前异步生成增量快照,前置备好撤回环境,更新失败可瞬时回滚
-
后台残留自动清理:更新完成、更新撤回、任务终止后,后台自动清理差分缓存、临时文件、无效配置,保持系统整洁
-
后台状态上报同步:安装结果、撤回结果、失败日志、设备版本基线后台自动同步至远程大表,完成运维闭环
-
后台自愈重试降级:更新异常后台自动梯度重试,多次失败后台自动标记设备兼容状态、停止推送问题补丁
3.4.3 后台任务场景适配规则
-
前台活跃场景:仅执行检测、下载、预缓存任务,延迟高IO安装任务,避免占用系统资源、造成卡顿
-
用户空闲/锁屏场景:自动放行全部后台安装、回滚、清理任务,全速完成更新迭代
-
低电量/流量受限场景:后台智能节流,暂停大体积补丁下载,仅保留紧急安全热修复流程,兼顾续航与资费
-
多用户切换场景:后台服务全局唯一,不受用户切换影响,跨用户持续完成系统级更新
3.4.4 后台权限与安全隔离机制
-
后台更新服务拥有系统专属更新权限,仅可操作更新指定文件目录与配置项,禁止越权篡改用户私有数据,权限最小化管控
-
所有后台操作全程日志溯源,记录操作时间、任务ID、执行步骤、结果状态,可审计、可追溯、可排查异常
-
非授权第三方程序禁止劫持、终止、篡改后台更新服务,保障更新链路安全不被劫持
3.4.5 后台与五级更新分级联动策略
-
level_urgent 紧急补丁:后台最高优先级插队执行,无视空闲策略、无视节流限制,即刻静默修复
-
level_recommend 推荐补丁:后台空闲自动下载、锁屏静默安装,延后次数由后台自动计数管控
-
level_preview 预览补丁:后台仅检测、不下发自动安装,等待用户前台确认后再执行后台任务
-
level_optional 可选补丁:后台仅版本比对、静默展示列表,不主动下载、不后台安装
-
level_dev 开发补丁:默认后台隐藏,仅开发者模式解锁后后台可见可更新
3.5 更新撤回与卸载回滚子系统(工业级完整闭环)
3.5 更新撤回与卸载回滚子系统(工业级完整闭环)
Novus OS 原生支持已完成更新的可逆撤回能力,支持所有增量补丁与小版本迭代更新一键卸载、还原更新前状态、自动清理更新残留、恢复原始文件权限与注册表配置,适配用户误更新、版本兼容异常、功能迭代不适配等场景,形成「更新-生效-撤回-复原」完整闭环。
本机制为系统原生底层能力,无需重装系统、不丢失用户数据、不破坏应用环境,区分「可撤回更新」与「永久固化更新」,权限分级可控、日志全程溯源。
3.5.1 撤回适用范围界定(永久冻结规则)
四类更新载体撤回权限差异化管控:
-
.apth 软件专属补丁:完全支持一键撤回,卸载后恢复软件旧版本、还原旧配置,无任何残留
-
.npth 系统通用累积补丁:支持常规小迭代更新撤回,仅重大核心基线更新固化不可撤回
-
.hotpth 紧急安全热修复补丁:默认禁止用户主动撤回,防止安全漏洞复现;仅系统底层故障自愈时自动静默回滚
-
.novu 全量大版本包:支持跨版本回滚至上一稳定大版本,保留用户数据分区,还原系统基线环境
3.5.2 更新快照增量存档机制(撤回核心底层)
系统摒弃全量备份冗余方案,采用增量快照存档,仅备份更新被修改、替换、删除的原始文件与配置,节省磁盘空间同时保证100%可复原:
-
每次更新成功写入后,自动生成「更新快照存档」,绑定当前补丁16进制唯一UUID
-
快照内容包含:原始文件二进制备份、文件权限掩码、目录结构、系统配置快照、服务启动项状态
-
快照生命周期可控:常规补丁默认保留30天快照,紧急安全补丁永久留存快照,大版本快照保留60天
-
过期快照自动后台轻量化清理,仅保留更新日志与版本溯源记录,不影响系统运行
3.5.3 系统更新索引注册表(撤回溯源核心)
系统内置专属更新索引数据库,记录每一条已安装更新的完整元数据,为撤回功能提供精准索引:
单条更新索引固定字段:
-
补丁16进制唯一UUID、文件后缀类型、更新分级等级
-
安装时间、安装状态、是否成功生效、是否已撤回
-
关联修改文件列表、差分块映射表、快照存档存储路径
-
可撤回标记、固化锁定标记、过期清理时间戳
-
更新版本前后基线号、适配系统版本区间
所有已安装更新在系统更新列表可视化展示,支持按时间、类型、版本筛选,用户可自主选择指定更新单独撤回,支持精准单条回滚、不影响后续其他更新。
3.5.4 分层撤回执行流程(原子事务级冻结)
撤回操作全程事务化,遵循「要么完全撤回、要么原样保留」的原子原则,杜绝半撤回异常状态:
-
前置校验:校验补丁合法性、快照完整性、当前系统基线匹配度,检测是否存在依赖后置更新
-
依赖检测:若当前更新被后续高阶更新依赖,弹窗提示依赖关系,支持「连带撤回后续增量更新」或「禁止单独撤回」
-
文件复原:依据增量快照覆盖还原原始文件、恢复权限、修复目录结构
-
配置回滚:还原系统服务项、开机自启、环境变量、应用配置旧状态
-
残留清理:自动删除本次更新新增冗余文件、无效注册表项、废弃差分缓存
-
状态刷新:静默刷新系统核心服务、桌面环境、应用挂载状态,无需冗余重启(内核级变更按需提示重启)
-
日志归档:记录撤回时间、操作主体、回滚结果,同步更新索引数据库状态
3.5.5 特殊锁定与豁免策略
-
安全补丁锁定策略:.hotpth 紧急安全修复永久锁定用户撤回入口,杜绝人为关闭安全防护导致漏洞暴露
-
基线固化策略:系统重大基线累积更新自动标记为固化版本,禁止普通用户撤回,保障系统底层稳定性
-
开发者豁免策略:开发者模式下可解锁全部撤回权限,支持任意版本回滚,适配调试与二次开发场景
3.5.6 服务端同步撤回策略
-
客户端撤回操作自动同步上报远程统一大表,服务端更新设备版本基线状态
-
针对批量设备灰度异常更新,服务端可远程下发「批量撤回指令」,全网统一回滚问题补丁
-
已撤回的问题补丁自动降级灰度放量比例,严重问题补丁全网下架、停止推送
3.5.7 撤回能力差异化总表
| 补丁类型 | 可用户撤回 | 可自动自愈回滚 | 快照保留周期 | 依赖联动策略 |
|---|---|---|---|---|
| .hotpth 紧急热修复 | 否(锁定保护) | 是(故障自愈) | 永久保留 | 禁止单独回滚,保障安全基线 |
| .npth 系统累积补丁 | 是(非基线版) | 是 | 30天 | 检测后续依赖,支持连带回滚 |
| .apth 软件补丁 | 是(完全开放) | 是 | 30天 | 独立应用隔离,无系统依赖 |
| .novu 全量版本包 | 是(大版本回退) | 是 | 60天 | 整体基线还原,清空增量迭代记录 |
3.4 稳定版更新延后管控策略
-
level_recommend 稳定推荐更新,支持用户自主延后1-3次更新,适配临时工作场景需求
-
延后次数耗尽后自动强制安装,避免设备版本长期滞后、漏洞堆积、兼容性断层问题
-
紧急安全热修复补丁不支持延后、忽略、拦截,保障系统安全底线
4. Novus OS 自研更新体系能力总览表
| 系统能力模块 | Novus OS 自研实现方案 | 能力状态 |
|---|---|---|
| 紧急安全漏洞修复 | .hotpth 最高优先级静默热修复体系 | 已完全落地冻结 |
| 系统核心累积迭代 | .npth 系统通用增量补丁体系 | 已完全落地冻结 |
| 用户软件独立更新 | .apth 应用软件专属增量补丁体系 | 已完全落地冻结 |
| 系统大版本升级 | .novu 全量安装包兜底方案 | 已完全落地冻结 |
| 远程统一更新管控 | 全局唯一大表 + 客户端后台轮询架构 | 已完全落地冻结 |
| 五级精细化更新分级 | 紧急/推荐/预览/可选/开发 全通道体系 | 已完全落地冻结 |
| 字节级增量差分更新 | 自研Delta差分数据块更新机制 | 已完全落地冻结 |
| 原子更新与事务回滚 | 快照备份+全自动异常回滚体系 | 已完全落地冻结 |
| 断点续传续更能力 | 下载与安装进度持久化机制 | 已完全落地冻结 |
| 智能时段调度更新 | 空闲识别+免打扰时段自定义策略 | 待编码落地 |
| 精细化灰度推送管控 | 设备维度百分比放量+白名单机制 | 已支持 |
| 更新失败自愈与重试 | 梯度重试+设备兼容拉黑+日志上报闭环 | 待编码落地 |
5. Novus OS 自研更新体系定位总结
Novus OS 更新体系为100%纯自研、完全独立知识产权、工业级稳定的操作系统原生更新架构,无任何第三方架构依赖,完全适配自研系统生态:
-
搭建了独有的「三类补丁格式+五级更新通道」分层更新模型,精准区分安全修复、系统迭代、软件更新场景,权责隔离、层级清晰。
-
采用轻量化服务端大表管控+客户端极简执行架构,兼顾批量运维效率与终端系统稳定性。
-
融合自研差分增量、原子事务回滚、断点续更、智能调度、灰度自愈核心能力,形成安全、高效、可控、可调试的完整更新生态闭环。
6. 后续开发落地清单
-
落地客户端智能空闲时段识别与分时更新调度逻辑
-
实现更新失败梯度重试、自愈检测、设备兼容拉黑机制
-
完善服务端大表设备维度百分比灰度推送、放量管控逻辑
-
完成稳定版更新延后次数统计、阈值管控、强制更新策略模块开发