TranquilOS
EN GitHub

权限分层,能力授权,服务隔离。

EL3 完成引导,EL2 运行 hypervisor,EL1 运行微内核,EL0 承载系统服务与应用。层间只通过 capability、IPC 和共享内存交互。

四层运行时,边界清晰。

启动自底向上沿 EL3 → EL2 → EL1 → EL0 交接;运行时通过 capability、IPC 与 SHM 通信。

EL0 EL1 EL2 EL3 Hypervisor Type-1 · 可选启动级 stage-2 VM/VCPU vGIC vTimer vPMU hypcall Microkernel capability 对象分发 capability migrating IPC SMP scheduler futex IRQ · timer drivers Bootloader 平台初始化 · 镜像装载 · 异常级交接 platform image load handoff boot handoff handoff SystemDaemon 特权 EL0 进程 · 17 个 IPC 方法 procmgr — 进程 / 线程生命周期 memmgr — 物理页分配 · SHM ipcmgr — endpoint 命名空间 virtmgr — VM 生命周期 直接发起 capcall,不经 libsyscall Framework Services 独立 EL0 进程 · endpoint pool 注册 windowmgr fsmgr netmgr devmgr appmgr audiomgr fontmgr statemgr timemgr agentmgr mmimgr imemgr 服务接口由 .idl 描述,wrapper / dispatch 代码生成 Applications 普通用户态程序 systemui launcher settings files monitor memo music calendar clock whiteboard calculator nes ai about IPC IPC

所有内核对象,只经 capability 访问。

每个进程用 CNode 保存可访问的内核对象。64 位 cref 由 cnode ID 与 slot 组成;每次分发前,内核检查对象类型与 rights mask。

VSpaceCNodeEndpoint SContextXContextTimer FutexIRQConsole
系统调用路径标识位用途
Capability callCAP_CALL_MASK路由到 capability 对象(VSpace、CNode、Endpoint、Timer…)
Fast callFAST_CALL_MASK内核内联高性能调用(当前为 stub)
Compact syscallLinux 兼容表;未知调用经 upcall 转交用户态 libsyscall 分发

upcall 是反向路径:内核把无法处理的系统调用、页错误等事件转交进程注册的用户态处理函数,让策略留在用户态。

跨进程调用,像函数调用。

同步 IPC 把调用方上下文直接迁入被调地址空间,不等待服务线程调度。

MIGRATING THREAD

只切执行上下文,不动调度状态

得益于 scontext / xcontext 分离:IPC 时内核构造目标进程的 execute_context_s,按 AAPCS 把参数放入 x0–x7,接口函数地址放入 pc,跳板函数地址放入 lr——接口返回时跳板发起 REPLY 调用切回调用方。调度元数据全程由调度器独立控制,IPC 再频繁也不会饿死其他线程。

ENDPOINT & POOL

单线程端点与弹性端点池

Endpoint 为单线程模型,一个 handler 线程处理一个端点;Endpoint Pool 在预分配的多个端点间负载均衡,支撑多线程服务(弹性 IPC)。客户端接口在两种模式下保持一致。内核内置 name service(cref 0x1),服务经 sys_register_service() 注册,客户端以 sys_get_service() 查找。

01alloc_shm

客户端向 SystemDaemon 申请共享内存。

02map & copy

映射 SHM 并写入请求数据。

03ipc call

发起 IPC,SHM 句柄作为参数传递。

04get_shm

服务端映射同一块 SHM。

05process

直接在共享数据上处理,零拷贝。

06reply & free

应答后客户端释放 SHM。

SHM 是进程间唯一的数据通道——TranquilOS 没有消息拷贝式 IPC,所有批量数据都走共享内存,IPC 参数槽只传句柄与标量。

调度与执行,是两份数据结构。

TCB 拆成调度实体与执行实体。每个 CPU 独立调度,只在真实切换时触碰寄存器状态;CFS 作为内核模块挂接。

per-CPU runqueueload balancing preemptiveCFS module
schedule_context_s   // 调度元数据
  · priority / timeslice
  · runqueue 节点 / CPU 亲和性
  · 由调度器与调度策略操作

execute_context_s    // 执行状态
  · x0–x30 · sp · pc · pstate
  · 仅在实际上下文切换时构造/恢复
  · IPC 迁移时独立构造,不经调度器

内核只留 boot allocator,内存策略在 EL0。

内核只保留启动期分配器。内存策略位于 SystemDaemon,由 procmgr、memmgr、ipcmgr 与 virtmgr 四个组件实现。

组件职责
procmgrspawn ELF、进程/线程销毁、PID 查找
memmgrbuddy 物理页分配、虚拟地址空间、SHM 管理
ipcmgrendpoint / pool 创建、命名服务、capability 克隆
virtmgrVM 创建与生命周期管理

启动:initcall 分级初始化,镜像布局固定。

链接器把初始化函数按 LV0–LV7 放入专用段,内核逐级执行;bootloader 根据 CurrentEL 决定先起 hypervisor 还是直入内核。

LV用途
0early_device_init最早期的设备初始化
1early_device_percpu_initper-CPU 早期设备
2key_device_init关键设备(GIC、timer…)
3key_device_percpu_initper-CPU 关键设备
4normal_device_init常规设备
5normal_device_percpu_initper-CPU 常规设备
6module_init内核模块(如 CFS)
7module_percpu_initper-CPU 模块初始化
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

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

首个用户态进程。解析设备树找到 ramdisk,拉起 devmgr 与 fsmgr,执行 /root/etc/init.rc

02zygote

读取 init.json,把服务 ELF 从 ext2 载入 SHM,经 start_process_from_shm() 启动框架服务。

03appmgr

applist.json 管理应用注册表,按需启动应用进程。

同一服务骨架,IDL 生成接口。

main.c 注册服务,service.c 分发方法,client/ 封装 IPC;生成器同时校验 ABI。

// service.c — 每个服务相同的分发模式
static handler_fn handlers[] = {
  [IPC_SERVICE_FUNCTION_CREATE] = handler_create,
  [IPC_SERVICE_FUNCTION_DESTROY] = handler_destroy,
  // ...
};

IPC_ENDPOINT void service_entry(
    uint64_t cref, uint64_t method,
    uint64_t a1, uint64_t a2, uint64_t a3) {
  if (method < HANDLERS_COUNT && handlers[method])
    OSIpcEndPointPoolReply(handlers[method](a1, a2, a3));
  else
    OSIpcEndPointPoolReply(0);
}
// statemgr_ipc.idl
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;
};

结构体指针使用服务端持有的固定接收缓冲区:首次调用按“调用方 + 方法 + 参数槽”建立 SHM 授权,后续复用连接级 CRef 与映射地址;每个方法用独立锁覆盖复制、IPC 与回写。传输结构体必须带 version,生成器附加 abi_size / abi_version 由服务端校验;变长数据显式传 SHM 句柄与长度。