☰
Droidspaces如何用5个Namespaces实现完美隔离?PID/MNT/UTS/IPC/Cgroup源码级深度解析
2026/10/7 8:32:13 网站建设 项目流程

Droidspaces如何用5个Namespaces实现完美隔离?PID/MNT/UTS/IPC/Cgroup源码级深度解析

【免费下载链接】Droidspaces-OSSA lightweight, LXC-like container runtime for Android and Linux. Run full Linux distributions natively with zero performance penalty项目地址: https://gitcode.com/gh_mirrors/dr/Droidspaces-OSS

Droidspaces是一个轻量级、类似 LXC 的容器运行时,专为 Android 和 Linux 设计,能在手机上原生运行完整的 Linux 发行版且零性能损耗。它的隔离魔法来自内核的 5 大隔离机制:PID、Mount、UTS、IPC 命名空间与 Cgroup 资源控制。本文将从源码角度带你快速看懂:Droidspaces 到底在哪里、按什么顺序调用了哪些unshare()系统调用,每个命名空间各自隔离了什么。

一、先看全局:5个隔离机制各管什么?

在深入源码前,先用一张表建立直觉:

隔离机制隔离内容Droidspaces 中的作用
PID 命名空间进程号与进程列表容器内 init 是 PID 1,看不到宿主机进程
Mount 命名空间挂载点与文件系统视图容器拥有独立的/、/proc、/sys、/dev
UTS 命名空间主机名与域名每个容器可以有自己的 hostname
IPC 命名空间共享内存、信号量、消息队列容器内 IPC 对象互不可见
Cgroup(+Cgroup NS)CPU/内存/进程数等资源限制容器资源,隔离/sys/fs/cgroup视图

💡 补充:在 NAT/无网络模式下,Droidspaces 还会额外创建NET 命名空间实现网络隔离,它属于可选能力,在 src/check.c 中被标记为 OPTIONAL。

二、启动前先自检:check.c 如何探测内核支持?

很多用户在 Android 上跑容器失败,其实是内核不支持某个命名空间。Droidspaces 的做法很聪明:不仅"看",还要"试"。

在 src/check.c 的check_ns()函数中,每一步分两关:

  1. 快速检查:探测/proc/self/ns/<name>是否存在,确认内核编译了对应支持;
  2. 功能检查:fork()出一个子进程并真正调用unshare(flag)试一次,成功才算通过(unshare会影响当前进程,所以必须用子进程来"沙盒试错")。

启动前的必需检查在 src/check.c:CLONE_NEWNS(文件系统隔离,必需)、CLONE_NEWPID(进程隔离,必需)、CLONE_NEWUTS(主机名隔离,必需)、CLONE_NEWIPC(IPC 隔离,必需)。而 Cgroup 命名空间则在 src/check.c 中被列为"推荐项"——因为它是 Linux 4.6+ 才有的特性。

三、三进程架构:谁在什么时候创建哪个命名空间?

这是 Droidspaces 源码里最有设计感的地方。它并不是"一个进程打包创建所有命名空间",而是把 5 个隔离点分配给三层进程,源码见 src/monitor.c:

父进程 fork → Monitor 监督者 → 中间进程 → 容器 init(PID 1) │ │ ├─ UTS + IPC └─ PID + Cgroup NS(+ NET) └─ 常驻,负责重启循环

为什么这么拆?源码注释解释得很直白(src/monitor.c):unshare(CLONE_NEWPID)每个进程只能调用一次。而 Droidspaces 支持容器内部执行reboot(2)后自动重启,每次重启都需要一个"全新的 PID 命名空间"。所以:

  • Monitor(监督者):启动时一次性unshare(CLONE_NEWUTS | CLONE_NEWIPC),这两个命名空间整个容器生命周期不变;
  • 中间进程:每次启动/重启循环都 fork 一个新的,unshare(CLONE_NEWPID)(外加可选的CLONE_NEWNET和CLONE_NEWCGROUP),然后 fork 出真正的容器 init;
  • 容器 init:成为新 PID 命名空间里的 1 号进程,随后执行internal_boot()完成剩余隔离。

这样"容器内部重启"时,旧的 PID 命名空间随旧 init 消亡,新循环里的一切干干净净,从机制上杜绝了"幽灵容器"。

四、Mount 命名空间 + pivot_root:文件系统隔离的主角

Mount 命名空间是五者中最复杂的,它的登场位置很特别:在容器 init 进程内部、所有其他准备工作之前(src/boot.c):

  1. unshare(CLONE_NEWNS)—— 拿到独立的挂载视图;
  2. mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, NULL)—— 把所有挂载点设为私有,防止容器内的挂载操作"泄漏"回宿主机。

源码注释特别提到一个 Android 细节:必须先用MS_PRIVATE起步,因为部分内核(比如 Android rootfs)上MS_SHARED会破坏pivot_root/MS_MOVE的回退路径。

随后internal_boot()按编号步骤依次完成(src/boot.c):

  • 第 4 步:把 rootfs 自绑定挂载(MS_BIND | MS_REC),这是pivot_root的前置条件;
  • 第 8~13 步:搭建/dev、挂载全新的procfs、sysfs、/run、/tmp(都是隔离的 tmpfs);
  • 第 17 步:真正的"换根"——pivot_root(".", ".old_root")把根目录切换到 rootfs;如果运行在 ramfs 环境(如 Android recovery)则自动回退到MS_MOVE + chroot组合,效果等同于switch_root。

换根完成后,宿主机文件系统就被彻底"甩在身后",.old_root随即卸载——这就是 Mount 命名空间给出的完整文件系统隔离。

五、UTS 与 IPC:轻量但不可或缺

这两个命名空间一次unshare就完成(src/monitor.c),成本低但作用明确:

  • UTS:容器可以独立设置主机名。网络配置阶段会通过sethostname()把配置的主机名写进容器(见 src/net/network.c),hostname命令输出的就不再是你的手机型号;
  • IPC:System V 共享内存、信号量、消息队列全部独立,容器内的进程无法通过 IPC 与宿主机或其他容器互相"串门"。

六、Cgroup:不只是限额,还有资源视图隔离

Cgroup 是 5 个机制里唯一"既管资源又管视图"的,实现在 src/cgroup.c,源码注释直言这是"移植自 LXC 风格的 Cgroup 配置":

  1. 建立层级:ds_cgroup_setup()从/proc/self/mountinfo发现宿主机的 cgroup 层级。Android 上很常见 cgroup2 只挂在/dev/cg2_bpf这类非标准位置,Droidspaces 会自己引导到/sys/fs/cgroup(src/cgroup.c);
  2. 加入与隔离:中间进程先ds_cgroup_join()进入容器的 cgroup,然后才unshare(CLONE_NEWCGROUP)——顺序很关键,因为 Cgroup 命名空间的"根"就是进程当前所处的位置,如果从根 cgroup 就进入命名空间就什么都隔离不了(src/monitor.c);
  3. 应用限额:按配置写入memory.max/memory.limit_in_bytes、cpu.max、pids.max(src/cgroup.c),分别对应内存、CPU 配额和进程数上限。

更妙的是:当设置了内存限额后,src/virtualize.c 还会"虚拟化"容器内/proc/meminfo等文件,让容器以为自己的内存就是限额值——对 systemd 等软件极其友好。

七、小结:隔离顺序 = 一张清晰的依赖图

把 5 个机制放回时间轴,你会发现 Droidspaces 的隔离顺序完全由依赖关系决定:

  1. UTS + IPC→ Monitor 常驻,一次到位;
  2. Cgroup join → Cgroup NS + PID NS(+ NET NS)→ 中间进程,为"可重启"而生;
  3. MNT NS → 私有挂载 → pivot_root→ 容器 init,完成最后换根。

这种"分层创建、各司其职"的设计,正是 Droidspaces 作为轻量级 LXC 替代品,却能在 Android 这类受限环境中稳定运行完整 Linux 发行版的关键。想动手验证的话,运行droidspaces check就能看到你的设备对这 5 项隔离能力的逐项体检报告。

核心源码索引:

  • 监督者与命名空间分层:src/monitor.c
  • 启动换根全流程(含 pivot_root):src/boot.c
  • 内核能力自检:src/check.c
  • Cgroup 层级与限额:src/cgroup.c
  • 功能特性说明:Documentation/Features.md
  • 内核配置要求:Documentation/Kernel-Configuration.md

【免费下载链接】Droidspaces-OSSA lightweight, LXC-like container runtime for Android and Linux. Run full Linux distributions natively with zero performance penalty项目地址: https://gitcode.com/gh_mirrors/dr/Droidspaces-OSS

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询