在未来 Fuchsia 会成为一个非常重要的操作系统。
重德智能工程师 许中兴如是说。
《世界需要新的操作系统-Fuchsia 设计解读》的学习笔记。
了解 Fuchsia 操作系统的基本情况、设计原理和优点,了解市场上各个操作系统的境况。
Fuchsia 的基本情况
- 全新的操作系统
- Google 开发
- 微内核,基于能力的访问控制,Vulkan 图形接口,3D 桌面渲染 Scenic,Flutter 应用开发框架,目前支持的编程语言:C/C++,Go,Rust,Dart
- 2016年,Google 放出所有代码,但是没有正式宣布项目目标,一个 IRC 频道交流
- 支持的架构 X86-64和 ARM 64,支持的设备从 IoT 到服务器
Google 为什么要从头设计全新的操作系统
- 737问题:当系统总体设计出现问题的时候,用再多的技巧去弥补,也只会造成最终的灾难
现代通用、开放 OS 需要面对的方面
- 上游硬件厂商
- 下游应用开发者
- 设备友商
- 用户
- 黑客
Fuchsia 解决现代 OS 痛点
- 原生进程沙箱,解决应用安全和分发问题
- Linux:Namespace,Control group,Unionfs => Docker
- 稳定的驱动接口,硬件厂商可独立维护硬件驱动
- 系统模块化,分层,设备厂商可以灵活定制专有系统
- 基于 Vulkan 和物理渲染的纯3D UI,全局光照
- Flutter 应用开发框架
Fuchsia 重新思考四个 Unix 的基础抽象机制
- 全局文件系统
- Unix,存在一个全局的根文件系统
- 它是每个进程共享的基础资源
- 文件系统涵盖了非文件资源:/proc, /sys, …
- Fuchsia 里,没有全局根文件系统
- 文件和文件系统成为一个局部概念,从而在进程内核数据结构里没有 file
- 用 Namespace 来定义一个进程能够访问的资源,每个 name 对应一个资源进程 channel 的 handle
- Unix,存在一个全局的根文件系统
- 用户
- Unix 中,User 本来是用作不同的用户登录,共享服务器的机制
- User 是真正的用户
- 后来主要用作权限控制,弱化的沙箱机制
- Fuchsia 中,在底层(Zircon,Garnet)没有用户的概念
- 用 namespace 来控制进程能够访问的资源
- Capability-based access control
- 从而在进程里没有 uid
- Unix 中,User 本来是用作不同的用户登录,共享服务器的机制
- 进程的创建
- Unix 中,新的进程由老的进程 fork 而来
- 新的进程继承父进程的全部资源
- 偷懒的设计
- Andrew Baumann, a fork() in the road, ACM Hot Topics in OS, May 2019
- Fuchsia 中,新进程需要从头开始创建
- 创建 process,Thread
- 父进程建立初始的 namespace 到资源 channel handle 的映射
- 调用 process_start 显式地告诉内核新的进程可以跑了
- 在 Fuchsia 内核的 process 数据结构中,没有 file 和 uid
- Unix 中,新的进程由老的进程 fork 而来
- 系统调用
- Unix 中,通过中断调用内核服务:int 0x80,syscall、sysenter 系统调用的方式是确定的,直接的
- 内核接口不能变
- 可以被任意注入的代码调用
- Zircon 里系统调用通过 vDSO 进行,意图是防止用户代码直接通过固定的中断代码调用 system call,达到内核详细接口的隔离,保持 C 层面的接口稳定:名字 + 参数。而不是内核入口汇编指令层面的稳定
- 注入的代码无法直接调用 vDSO 里的接口,虽然加载地址固定,但是计算出入口地址很难,如果不是不可能的话
- 内核会验证调用指定的地址,而 vDSO 的加载地址是固定的,并且在编译的时候会验证有限的入口符号,这些符号的偏移量在编译时生成,防止用户进程绕过 vDSO
- 这里主要的目的是隔离 system call 的调用方式,而不是绝对杜绝注入调用
- Unix 中,通过中断调用内核服务:int 0x80,syscall、sysenter 系统调用的方式是确定的,直接的
仿佛是专门针对漏洞利用作出的设计
- 典型的漏洞利用步骤
- 通过系统调用 fork()/exec()直接创建反向 shell
- 继承 uid 获得泛在授权
- 访问全局文件系统
- 在 Fuchsia 里,以上机制都不存在
- 没有固定的系统调用入口
- 创建进程时显式建立 root namespace
- 没有 user,从而没有 ambient authority (DAC/MAC)
- Capability-based access control
- 能访问的资源是父进程赋予的 namespace,看不到初始 namespace 之外的任何资源
Kernel 的本质是什么?
- 不是
- 管理硬件
- 执行特权指令
- 引导启动过程
- 处理中断
- 作者的理解:地址空间切换
- 不同进程唯一共享内存地址空间的场合
- 切换地址空间是进入内核的标志
- 不同的进程通过共享内核地址空间来交换信息
- 切换地址空间是切换进程的关键步骤
- Zircon 主要内核态功能
- 虚拟内存和物理内存管理
- 进程和线程管理
- 进程间通信
- 以内存为中心的设计
- VMO 代表一个内存对象,懒分配
- VMO 通过向 channel 发送 handle 在进程之间传递,进程拿到 VMO handle,把 VMO 重新映射到自己的地址空间里
- Unix 是以文件为中心的设计
- Channel
- 是进程间通信的唯一机制
- 一个 channel 有两个 handle,h1,h2,从一头写入消息,从另一头读出消息
- 进程启动时会拿到一些初始 channel handle
- 要与一个服务建立通信,h1自己拿着,h2发送给相应的服务做监听
- channel_write() 必须是一个系统调用
- 系统调用 vDSO
- 微内核
- 性能问题
- 上下文切换
- 线程切换
- 性能问题
Fuchsia 在各个平台上的可能的优势
- 服务器平台,原生进程沙箱机制将带来新的安全特性和容器机制
- 桌面平台,无缝兼容 Android
- 移动平台,系统的模块化方便第三方设备厂商的全面定制
Fuchsia 分层
- 四层,上面两层可以替换掉,不影响兼容性
- 用户体验层(Topaz)
- 应用框架层(Peridot)
- 系统服务层(Garnet)
- 内核层(Zircon)
Fuchsia 目前的运行环境
- 在 Qemu 中可以直接运行
- Bootloader 加载到0x40080000
- 内核加载到0x40090000
- Ramdisk 加载到0x48000000
- 0x40000000 - 0x40080000之间是 FDT flattened device tree
系统软件研发能力的获得
- 系统软件与应用软件不同
- 大量缄默知识
- 工具链:gcc,ld,as,clang,ELF
- 微处理器
- 周边设备 UEFI,ACPI,APIC,PCIE,USB,SATA,AHCI,GPU…
- 知识存在于代码中,硬件标准文档内容太多
- 产品级的设计非常困难
总结
- Fuchsia 重新思考了操作系统设计的各个方面,是一次难得的从头开始的机会
- 在未来 Fuchsia 会成为一个非常重要的操作系统
- 世界需要新的操作系统
- 每一个大型软件系统都值得尊重
- Windows 老态龙钟,历史负担太重,微软自己的创新 Midori 胎死腹中,因为无法承受在新的框架中重新实现一遍 Windows 的全部功能,只能在原地进行重构
- Linux 里大部分开发人员只关心服务器的世界,就像一个专注于在甲板下面锅炉房里干活的锅炉工
- MacOS,iOS 封闭在苹果的硬件生态里
- Android 为了弥补 Linux 的缺点打上了一个厚厚的中间层,不断在做着妥协
- GNU Hurd 作为 GNU 项目“最后的组件”一直未能产品化,原因是“微内核消息传递机制 debug 态困难”?
- Unix 的后继者 Plan 9 于2002年发布了最后一个版本,它的余热随着作者融入了 Go