Anbox 安装过程分析
Anbox 是在像 Ubuntu 这样的普通 GNU/Linux 系统上,基于容器启动完整 Android 系统的方案。
当前安装过程由多个步骤组成,这些步骤将向主机系统中添加额外的组件,这些组件包括:
- 由于没有发行版内核同时启用 binder 和 ashmem,因此需要它们的源码树之外的内核模块
- 为
/dev/binder
和/dev/ashmem
设置正确权限的 udev 规则 - upstart 或 systemd 任务,用于作为用户会话的一部分启动 Anbox 会话管理器。
为了使 Anbox 的安装过程尽可能简单,Anbox 官方已经在一个 snap (参考 https://snapcraft.io) 中打包了必须的步骤,称为 “anbox-installer”。这个安装器将执行所有必须的步骤。可以通过运行如下命令,在系统上安装 Anbox 提供对 snaps 的支持:
另外,还可以通过如下命令获得安装器脚本:
要通过 Anbox 的安装器脚本安装 Anbox 的话,简单地调用即可:
这将指导我们完成安装过程。
anbox-installer
安装器脚本的实现是这样的:
anbox-installer
安装器脚本中的 echo 打印输出有点多,同时这个脚本还提供了移除 anbox 的功能。安装 Anbox 的工作主要由如下这几行代码完成:
这段代码,通过三个步骤完成 Anbox 的安装。
第一步,安装 anbox-common
anbox-common
包的安装的文件如下:
第二步,安装 binder 和 ashmem 驱动
第三步,通过 snap 的方式安装 anbox 包
anbox 包通过 snap 的方式进行安装。
Anbox 容器管理服务
整体看来,Anbox 的安装过程安装了两个组件,一是 binder 和 ashmem 内核驱动;二是 Anbox,Anbox 又由 anbox-common 和 anbox snap 组成。
通过如下命令可以看到 anbox snap 的信息:
anbox 向主机系统中安装了 2 个命令,anbox
和 anbox.collect-bug-info
,以及一个 service,anbox.container-manager
,即 Anbox 的容器管理器服务。
通过 Anbox 安装器安装 Anbox 之后,service 会自动启动。通过如下命令可以查看这个服务的当前状态:
当 Anbox 的容器管理服务正常运行时,通过在应用列表中,点击 Anbox 应用,如下图这样:
可以启动 Anbox 会话。
当 Anbox 的容器管理服务起动时,它会监听一个 Unix 域 Socket,/run/anbox-container.socket
。(这个地址在 anbox/src/anbox/container/service.cpp
文件的 Service::create()
函数中,从 anbox::SystemConfiguration::container_socket_path()
获得)。
当启动 Anbox 应用,即会话管理器时,它会通过 Unix 域 Socket 与容器管理服务建立连接。容器管理服务接收到连接,且容器还没有启动时,它会挂载 Android 系统镜像,起动 LXC 容器,并在容器内起动 Android 系统。
同时会话管理器与主机系统上的 ADB 服务建立连接。如:
此时可以通过 adb
命令查看 Anbox 起动的 Android 系统的状况,如下面这样:
当 Anbox 起动的 Android 系统内所需的应用程序都启动完毕时,通过 Anbox 应用将可以看到 Android 系统的桌面,可以看到 Android 系统中的应用,如下图:
Anbox 项目写了一个名为 org.anbox.appmgr
的 Java 应用程序,用以替代原始 Android 系统中的 Launcher,以展示已安装应用列表。随后就可以像操作普通的桌面 Linux 系统中的应用那样操作 Android 内的应用了。
此时,查看主机 Linux 系统中与 Anbox 有关的进程,可以看到如下这些:
进程号为 30438 和 30644 的两个进程组成了容器管理器服务。进程号为 30630 的进程为我们启动的 Anbox 应用。进程号为 30652,30711,和 31209 的几个进程,实际为 Anbox 启动的容器中运行的 Android 系统的进程。Anbox 的整体设计可以参考 Anbox 一文。
Anbox snap
Anbox 应用通过 snap 方式打包,下载 anbox 的源码,并在源码目录下执行 snapcraft,可以生成 anbox 的 .snap 文件:
生成的 .snap 文件还可以通过如下命令进行安装:
通过 Anbox 的 snapcraft.yaml
文件,可以对 Anbox 运行时、命令和服务有更深入的了解。Anbox 的 snapcraft.yaml
文件长这样:
从 Anbox 的 snapcraft.yaml
文件中可以看到,Anbox snap 安装的几个命令和服务,是一些脚本:
Anbox snap 主要由这几部分组成:
- Android 系统镜像,先找本地的
android-images/android.img
,如果找不到,就根据主机系统的 CPU 架构,从远端下载 - anbox-common,主要是一些脚本,提供 Anbox snap 的命令和服务,由
source:
行可以看到这些脚本都位于源码目录的scripts
子目录下 - apparmor,从 Ubuntu 的 APT 源获得
- lxc,用于做容器管理,从 GitHub 获得源码,并由 tag 为 lxc-2.0.7 的版本编译生成
- anbox 二进制可执行程序,通过 cmake 编译生成,如:123456$ git clone https://github.com/anbox/anbox.git$ cd anbox$ mkdir build$ cd build$ cmake ..$ make
还可以通过如下命令编译带符号的 Debug 版 anbox 二进制可执行程序:
或 Release 版:
这里来看一下 Anbox snap 的主要命令和服务,也就是几个脚本的实现。container-manager.sh
脚本,用于起动容器管理服务,其内容如下:
在这个脚本中,启动容器管理服务时,调用 anbox-bridge.sh start
脚本为 Anbox 创建虚拟网卡,并调用 anbox-wrapper.sh
启动 anbox 二进制可执行程序。脚本的执行依赖几个环境变量的设置。在脚本执行时,环境变量 SNAP
指向 /snap/anbox/current
,环境变量 SNAP_COMMON
指向 /var/snap/anbox/common
。
anbox-wrapper.sh
也就是 anbox 源码库中的 scripts/snap-wrapper.sh
,其内容如下:
在这个脚本中,主要导出了一些环境变量,LD_LIBRARY_PATH
,XDG_CONFIG_DIRS
,XDG_DATA_DIRS
,LIBGL_DRIVERS_PATH
和 XDG_DATA_HOME
,以使 anbox 二进制可执行程序在启动之后,可以找到所需的动态链接库等。
打赏
参考文档:
Upstart
浅析 Linux 初始化 init 系统,Systemd
Debug vs Release in CMAKE