TranquilOS
EN GitHub
没有匹配的章节 — 换个关键词试试。

项目简介

TranquilOS 是面向 AArch64 的 object-capability 微内核操作系统。系统以 capability 作为统一授权模型,将进程管理、内存管理、IPC 命名空间、设备抽象、文件系统、网络协议栈、窗口合成与应用生命周期拆分为边界清晰的用户态服务——硬件驱动同样以独立进程(driver daemons)运行,由 devmgr 注册表按类转发;EL1 微内核专注于调度、IPC、异常、中断、定时器、futex、基础驱动与 capability 对象分发。

设计参考了 seL4 等内核的对象能力模型,目标是在 AArch64 平台上验证「微内核 + capability 授权 + 用户态系统服务」的系统化组合:内核对象如何被显式授权、服务如何发现与通信、图形桌面如何作为普通用户态组件运行、构建系统如何把分散组件组装为可启动镜像。

完整设计文档在内核仓库 docs/ 目录:basic_theory.md(AArch64 架构、MMU、上下文切换、驱动、capability、IPC、调度)、microkernel_design.md(微内核设计)、idl.md(接口定义与代码生成)、async_ipc_design.md

快速开始

前置条件:从 newos.org/toolchains 下载交叉工具链并解压到仓库 toolchains/;macOS 需要 brew install e2fsprogs(组装 ext2 system.img)。env_setup.sh 必须在每个新 shell 中 source,其中 OS_BASE_DIR 硬编码为 ~/kernel,仓库检出到其他路径时先修改。

# QemuVirt(主要开发平台):构建 + 组装镜像 + 启动 QEMU
source env_setup.sh && ./run_qemu_virt.sh

# 手动构建
source env_setup.sh
gn gen out --args='platform="QemuVirt"'
ninja -C out

# 单目标构建
ninja -C out Windowmgr

QEMU 配置:4 核 SMP、2G 内存、macOS 上 HVF 硬件加速、ramfb 显示、VirtIO tablet/keyboard/network/block/sound。其他平台:run_qemu_pi3b.sh(headless 串口)、run_qemu_pi4b.sh(SD 卡镜像)、run_board_cm4.sh(真机,经 rpiboot 刷写)。

仓库结构

sys/             系统基础(TCB)
  kernel/        微内核(EL1)
  virt/          Type-1 hypervisor(EL2)
  boot/          Bootloader
  trustee/       可信执行环境(stub)
  uapps/         启动与核心服务:base/ init、idle;core/ devmgr、fsmgr、drivers/(driver_mgr IDL)
  ulibs/         libc、libcrt、libsyscall、libsystem、libsync、libfdt、libalgorithm
os/              OS 用户态
  base/          zygote、netmgr
  framework/     windowmgr、mmimgr、appmgr、audiomgr、fontmgr、statemgr 等
  apps/          用户应用
  libs/          libwindow、libgraphics、libgl、liblvgl、liblwip 等
  thrid_party/   lvgl、freetype、mbedtls、lwip、musl 等三方源码
platform/        平台配置:QemuVirt / Pi3b / Pi4b / CM4(DTB、链接脚本、脚本;vendor/ 驱动 daemon 与 drivers.json)
build/           GN 构建系统与工具链定义
images/          ramdisk(cpio)、vendor 与 system 镜像模板
docs/            设计文档

三方库约定:不直接修改上游源码,平台适配与兼容封装集中在 os/libs/sys/ulibs/;升级三方库时整目录替换并验证适配层。

启动链与权限模型

TranquilOS 把 ARMv8-A 异常级别用作架构边界:EL2 运行可选的 Type-1 hypervisor,EL1 是微内核,EL0 承载 SystemDaemon、框架服务与应用。bootloader 根据 CPU CurrentEL 决定启动路径:

从 EL2 启动:bootloader → hypervisor → kernel → systemd
从 EL1 启动:bootloader → kernel → systemd

hypervisor 提供 stage-2 地址转换、VM/VCPU/PCPU 生命周期管理、vGIC、vTimer、vPMU 与 hypcall 接口;虚拟机与内核一同打包进 boot.img。

用户态启动顺序:init(首个用户态进程)解析设备树找到 ramdisk,拉起 devmgr 与 fsmgr,执行 /root/etc/init.rc——其中 exec 行以显式 linear-map 三元组拉起启动关键的 block 驱动 daemon;zygote 读取 init.json,把服务 ELF 从 ext2 载入 SHM 后调 start_process_from_shm() 启动框架服务,并读取 vendor 分区的 drivers.json 拉起其余驱动 daemons;appmgrapplist.json 管理应用注册表并按需拉起应用。

Capability 系统

capability 是内核对象与细粒度权限的统一管理结构,也是用户态与微内核交互的统一方式。用户态对内核的所有操作可归结为「对某个内核对象执行某个方法」:OS_{Type}{Method}(ref, args...)——权限因此可以细化到每个对象、每个方法。

每个进程拥有 CNode 保存其全部 capability。CNode 由 directory array 构成:兼具数组索引的速度与动态数组的扩展性,扩展时不拷贝、保持线性索引。capability 引用(cref)为 64 位:高 32 位是 cnode ID,低 32 位是 slot 索引;根 CNode ID 为 1。方法分发前内核校验对象类型与 32 位 rights mask。

内核对象类型包括:VSpace(虚拟地址空间)、CNode(capability 存储)、SContext / XContext(调度 / 执行状态)、IPC Endpoint / Pool、Timer、Futex、IRQ、Console。

内存管理

内核只保留 boot allocator,为内核启动阶段与 SystemDaemon 运行分配内存;全部内存策略都在用户态。SystemDaemon 的 memmgr 以 buddy 分配器管理物理页,并管理进程的虚拟地址空间与 SHM 共享内存。

内核侧覆盖 AArch64 MMU 的完整配置:MAIR/TCR、block/table 描述符、identity map、ASID 与 TLB 管理;VSpace 对象代表一个进程的地址空间,经 capability 调用操作。

IPC 模型

传统内核的进程间同步(socket、pipe、共享内核缓冲)响应依赖调度器行为,延迟不确定。TranquilOS 提供控制流立即切换的迁移线程 IPC:client 发起同步调用时,内核把 server 地址空间与一个构造好的 execute_context_s 装上 CPU——参数按 AAPCS 放入 x0–x7,接口函数地址放入 pc;lr 中放入跳板函数地址,接口返回时跳板发起 REPLY 调用切回 client。调度元数据全程由调度器独立控制,IPC 不影响调度公平性。

  • IPC Endpoint:单线程模型,一个 handler 线程服务一个端点。
  • Endpoint Pool:在预分配的多个端点间负载均衡,支撑多线程服务;其上构建弹性 IPC
  • Upcall:内核 → 用户态的反向调用,用于系统调用转发、页错误等事件。
  • Name service:内核端点 cref 0x1。服务以 sys_register_service() / sys_register_service_pool() 注册,客户端以 sys_get_service() / sys_get_service_pool() 查找。

调度器

传统 TCB 被拆分为执行实体 execute_context_s(x0–x30、sp、pc、pstate 等寄存器状态)与调度实体 schedule_context_s(优先级、时间片、队列节点、CPU 亲和性)。per-CPU 调度器只操作调度元数据,真正切换上下文时才构造 / 恢复执行状态——这也让迁移线程 IPC 的实现大为简化。

SMP 下每个 CPU 有独立本地调度器并做跨核负载均衡,支持抢占。CFS 调度类以可加载内核模块实现(sys/kernel/module/),验证模块系统的真实可用性。

系统调用路径

系统调用号在 x8 中,按标识位走三条分发路径:

路径标识位用途
Capability callCAP_CALL_MASK路由到 capability 对象:VSpace、CNode、IPC endpoint、Timer 等,capcall 是微内核的主要系统调用
Fast callFAST_CALL_MASK内核内联的高性能调用(当前为 stub)
Compact syscallLinux 兼容表(目前仅 getpid);其余经 upcall 转交进程注册的用户态 handler(libsyscall 函数表分发)

initcall 初始化

初始化函数经宏放入专用 ELF 段,链接脚本为每级定义起止符号,initcall_run(level) 按 LV0 → LV7 顺序执行:

LV用途
0early_device_init最早期设备初始化
1early_device_percpu_initper-CPU 早期设备
2key_device_init关键设备
3key_device_percpu_initper-CPU 关键设备
4normal_device_init常规设备
5normal_device_percpu_initper-CPU 常规设备
6module_init内核模块
7module_percpu_initper-CPU 模块初始化

SystemDaemon

SystemDaemon 运行在 EL0,是最高特权的用户态进程,链接在 0x43080000,直接发起 capcall(libkernel/capcall.h)而不经 libsyscall。传统内核中的高层资源管理由它承担,各组件以单例对象管理以约束接口暴露:

  • procmgr:进程 / 线程生命周期,ELF 装载(spawn、exit、PID 查找)
  • memmgr:物理页分配、SHM 共享内存管理
  • ipcmgr:IPC endpoint / pool 创建、name service、capability 克隆
  • virtmgr:虚拟机管理

对外通过 systemd_client.c 暴露 17 个 IPC 方法,数据传递走 SHM。vfs、devmgr 等核心服务也由它拉起。

框架服务模式

每个 OS 服务(os/framework/*sys/uapps/core/*)遵循相同结构:

main.c            初始化、经 IPC 注册服务、事件循环
service/service.c 按方法号分发的 IPC handler 表,调用内部处理函数
client/           薄 IPC 客户端封装,用 SHM 传数据
include/          服务内部头文件
client/include/   公开客户端 API 头文件

分发模式在所有服务中一致:handler 函数指针表按方法号索引,service_entry 校验方法号后调用对应 handler 并以 OSIpcEndPointPoolReply() 应答;启动时以 sys_register_service_pool(IPC_SERVICE_ID_*, &service_entry) 注册。

SHM 数据传递

进程间所有数据传输都使用共享内存,这是唯一的数据通道——没有消息拷贝式 IPC。通用流程:

  • 客户端经 systemd->ops.alloc_shm() 申请 SHM
  • 映射并写入数据
  • 发起 IPC 调用,SHM 句柄作为参数传递
  • 服务端经 systemd->ops.get_shm() 映射同一块 SHM
  • 直接处理共享数据(零拷贝)
  • 应答;客户端释放 SHM

服务清单

服务职责
appmgr应用生命周期:注册表、按需拉起
windowmgr窗口合成器与 surface 管理、输入分发
statemgr系统级 KV 状态存储
devmgr驱动 daemon 注册表与按类 IPC 转发;外设管理
fsmgr文件系统抽象:rootfs、ext2、FAT32、procfs、sysfs
netmgrlwIP TCP/IP 网络栈
mmimgr多模态输入管理
audiomgr音频服务
fontmgrFreeType 字体渲染
agentmgrAI agent 框架
timemgr计时、RTC 闹钟、NTP 同步
imemgr输入法编辑器

IDL 与代码生成

服务用 .idl 文件描述同步 IPC 接口,生成器(tools/idl_gen.py,通常由 GN 构建任务自动调用)产出五个文件:<service>_types.h<service>_client.h/.c<service>_service.h/.c

service statemgr_ipc {
    id = 0x9;

    struct query  { version = 1; char key[64]; };
    struct result { version = 1; uint32_t found; };

    uint64_t get(in query *request,
                 out result *response) id = 0x1;
};

参数方向控制生成代码的拷贝行为:in IPC 前复制进 SHM,out IPC 前清空、IPC 后复制回,inout 两者兼有(未标注的结构体指针默认 inout);标量直接走 IPC 参数槽,每方法最多三个参数。

服务端接收缓冲区:结构体指针使用服务端持有的固定缓冲区。首次调用按「调用方 + 方法 + 参数槽」建立 SHM 授权;客户端保存连接级 CRef 与映射地址,后续调用直接复用。每个方法用独立锁覆盖输入复制、IPC 与输出复制;变长或调用方持有的大块数据仍显式传 SHM 句柄与长度。

传输与映射:默认经 endpoint pool IPC、经 SystemDaemon 映射 SHM;可用服务属性切换 transport = endpointmapping = direct

ABI 规则:传输结构体必须声明 version > 0;生成器附加 abi_size / abi_version 字段,服务端在调用处理函数前校验。传输结构体不允许指针字段(指针只在所属进程地址空间有效)。完整语法见 tools/idl_ref/tranquil_idl.ebnf

GN 构建目标

目标类型用途
executable()ELF:kernel、SystemDaemon、框架服务、应用
source_set()编译进每个使用者的库(不产出独立 .a)
group()依赖打包的元目标(如 uapp_runtime
config()编译 / 链接标志包,经 configs += 应用

每个 executable 链接平台专用链接脚本(platform/$PLATFORM/linker/*.lds),用户态可执行文件用 libcrt/uapp.lds,且必须把 libcrt/start.S(提供 _start)列为首个源文件。常用依赖组://sys/ulibs:uapp_runtimeuapp_runtime_with_syscall//sys/ulibs/libsystem:systemd_client

平台与镜像

平台定位说明
QemuVirt主要开发平台设备组合最完整(ramfb、VirtIO 全家桶),内核改动先在此验证
Pi3B(QEMU)平台验证-nographic 串口,headless
Pi4B(QEMU)平台验证MBR 分区 SD 卡镜像(mkpiimg.sh)
CM4真实硬件经 rpiboot USB 刷写,需实体底板
boot.img (64MB)
  offset 0      Bootloader    8MB
  offset 2048   DTB           8MB
  offset 4096   Hypervisor   16MB
  offset 8192   Kernel       16MB
  offset 12288  SystemDaemon  8MB
  offset 14336  Ramdisk cpio  8MB

vendor.img (32MB, ext2, P2)
  bin/  driver daemons (.drv)
  etc/  drivers.json

system.img (128MB, ext2)
  bin/  framework services
  apps/ user applications
  etc/  fonts · icons · init config