只切执行上下文,不动调度状态
得益于 scontext / xcontext 分离:IPC 时内核构造目标进程的 execute_context_s,按 AAPCS 把参数放入 x0–x7,接口函数地址放入 pc,跳板函数地址放入 lr——接口返回时跳板发起 REPLY 调用切回调用方。调度元数据全程由调度器独立控制,IPC 再频繁也不会饿死其他线程。
EL3 完成引导,EL2 运行 hypervisor,EL1 运行微内核,EL0 承载系统服务与应用。层间只通过 capability、IPC 和共享内存交互。
启动自底向上沿 EL3 → EL2 → EL1 → EL0 交接;运行时通过 capability、IPC 与 SHM 通信。
每个进程用 CNode 保存可访问的内核对象。64 位 cref 由 cnode ID 与 slot 组成;每次分发前,内核检查对象类型与 rights mask。
| 系统调用路径 | 标识位 | 用途 |
|---|---|---|
| Capability call | CAP_CALL_MASK | 路由到 capability 对象(VSpace、CNode、Endpoint、Timer…) |
| Fast call | FAST_CALL_MASK | 内核内联高性能调用(当前为 stub) |
| Compact syscall | — | Linux 兼容表;未知调用经 upcall 转交用户态 libsyscall 分发 |
upcall 是反向路径:内核把无法处理的系统调用、页错误等事件转交进程注册的用户态处理函数,让策略留在用户态。
同步 IPC 把调用方上下文直接迁入被调地址空间,不等待服务线程调度。
得益于 scontext / xcontext 分离:IPC 时内核构造目标进程的 execute_context_s,按 AAPCS 把参数放入 x0–x7,接口函数地址放入 pc,跳板函数地址放入 lr——接口返回时跳板发起 REPLY 调用切回调用方。调度元数据全程由调度器独立控制,IPC 再频繁也不会饿死其他线程。
Endpoint 为单线程模型,一个 handler 线程处理一个端点;Endpoint Pool 在预分配的多个端点间负载均衡,支撑多线程服务(弹性 IPC)。客户端接口在两种模式下保持一致。内核内置 name service(cref 0x1),服务经 sys_register_service() 注册,客户端以 sys_get_service() 查找。
客户端向 SystemDaemon 申请共享内存。
映射 SHM 并写入请求数据。
发起 IPC,SHM 句柄作为参数传递。
服务端映射同一块 SHM。
直接在共享数据上处理,零拷贝。
应答后客户端释放 SHM。
SHM 是进程间唯一的数据通道——TranquilOS 没有消息拷贝式 IPC,所有批量数据都走共享内存,IPC 参数槽只传句柄与标量。
TCB 拆成调度实体与执行实体。每个 CPU 独立调度,只在真实切换时触碰寄存器状态;CFS 作为内核模块挂接。
schedule_context_s // 调度元数据
· priority / timeslice
· runqueue 节点 / CPU 亲和性
· 由调度器与调度策略操作
execute_context_s // 执行状态
· x0–x30 · sp · pc · pstate
· 仅在实际上下文切换时构造/恢复
· IPC 迁移时独立构造,不经调度器
内核只保留启动期分配器。内存策略位于 SystemDaemon,由 procmgr、memmgr、ipcmgr 与 virtmgr 四个组件实现。
| 组件 | 职责 |
|---|---|
| procmgr | spawn ELF、进程/线程销毁、PID 查找 |
| memmgr | buddy 物理页分配、虚拟地址空间、SHM 管理 |
| ipcmgr | endpoint / pool 创建、命名服务、capability 克隆 |
| virtmgr | VM 创建与生命周期管理 |
链接器把初始化函数按 LV0–LV7 放入专用段,内核逐级执行;bootloader 根据 CurrentEL 决定先起 hypervisor 还是直入内核。
| LV | 宏 | 用途 |
|---|---|---|
| 0 | early_device_init | 最早期的设备初始化 |
| 1 | early_device_percpu_init | per-CPU 早期设备 |
| 2 | key_device_init | 关键设备(GIC、timer…) |
| 3 | key_device_percpu_init | per-CPU 关键设备 |
| 4 | normal_device_init | 常规设备 |
| 5 | normal_device_percpu_init | per-CPU 常规设备 |
| 6 | module_init | 内核模块(如 CFS) |
| 7 | module_percpu_init | per-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
首个用户态进程。解析设备树找到 ramdisk,拉起 devmgr 与 fsmgr,执行 /root/etc/init.rc。
读取 init.json,把服务 ELF 从 ext2 载入 SHM,经 start_process_from_shm() 启动框架服务。
按 applist.json 管理应用注册表,按需启动应用进程。
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 句柄与长度。