用电纸书跑一些大一点的应用很吃力,所以我需要一个强劲一点的CPU,最好是Intel的CPU,果然有这样的机器,还十分符合我的要求。那就是华硕的zenfone2,虽然已经是2015年的设备了,但是配置非常的豪华,4g的内存,16-64G的存储空间,还有一个256G的版本,目前没有见过。我在闲鱼上的淘了一个32G的版本,有了Intel的CPU再加上KVM内核,跑完整版本的windows或者Linux都没有问题,raw格式是最快的了,但是镜像文件会比较大,不方便进行迁移,安装windows系统,我会选择稍慢一点的qcow2格式。

zenfone2官方andorid 5 rom的内核版本比较低,功能上会有比较多的限制,用虚拟机来跑Linux,使用起来会更加方便。虚拟机中的Linux,并不需要安装一个像Debian一样的功能完备的Linux发行版,最好是一个启动迅速小巧的发行版,一番调查实验下来,发现boot2docker是最佳的选择。虽然boot2docker官方没有提供qemu的docker-machine驱动,但github上有人开发了一个,这个驱动需要自己编译,release版本功能比较少。为了提高虚拟机的性能重新编译了android内核,添加kvm、9p和virtio相关的内核模块,9p内核模块可以将主机的目录挂载到Linux虚拟机中。

1 编译内核

1.1 下载android源代码

刚开始使用自己的代理来下载,对比需要下载的数量来看,代理的速度太慢了,幸亏中科大有镜像。刚开始使用清华大学的镜像,出问题了,总是出错,还是中科大的镜像靠谱一点。 有一个叫xxx子项目是不能同步的,需要注释掉这个项目。 先下载一个打包好的初始镜像,解包后,再运行同步命令,同步某个android版本的时候,设置shell变量,可以改变同步代码源,你也可以直接修改repo脚本,把 REPOURL 一行替换成下面的: ## REPOURL = 'https://gerrit-googlesource.proxy.ustclug.org/git-repo'

REPO_URL='https://gerrit-googlesource.proxy.ustclug.org/git-repo'
repo init -u git://mirrors.ustc.edu.cn/aosp/platform/manifest -b android-4.0.1_r1
repo sync

1.2 Debian stretch安装openjdk-7

你也可以安装Oracle的jdk,下载好了之后,设置好环境变量就好了,我需要使用emacs来调试java程序,openjdk可能更加适合。 How do I install openjdk 7 on Ubuntu 16.04 or higher?

1.3 大神的一句话,道破了成功编译的玄机

我一直没有成功从zenfone2的开源内核源代码中编译出bzimage,大神的一句话道破了玄机,要先下载第一个版本的内核,然后把最新的版本覆盖到这个目录中,才能成功编译,不能下载源代码解压就直接编译。 fhd kernel ( ZE551 ) & POSSIBLY hd (ZE550) with KVM & Bridge compiled. need help 第5页

You will also want to make sure you untar the first kernel source, Asus left out components in later kernel source so they won't compile unless you untar them over the first one. 

xda上say99他的github上的内核是直接可以编译的,不需要下载巨大的android源代码。 Flare-AEL-X是官方版本android5的内核,kernel-FlareM是官方版本android6的内核,还有一个aosp的内核。 CONFIGDEBUGINFO 这个选项不选,可以大大减少内核和内核模块的大小。 say99写的编译内核教程《Compile your own kernel》 我估计没几个人像我这么折腾的,详细的编译过程就不再叙述了,如果编译碰到困难或者真的需要我的编译的内核就留言给我吧。

1.4 制作Boot分区镜像boot.img

1.4.1 解包官方Rom中的boot.img

到华硕官网下载Android 5的最新版本,找到boot.img解压出来。为什么选择Android 5而不选择Android 6,因为Android 6下的Linux Deploy不能安装64位的Linux,用32位总感觉会稍慢一点,CPU是64位的,就不要浪费它的寻址能力。而且我主要用的是Linux系统,Android版本对我的影响比较小,低版本消耗的资源还更小一点。

unpackbootimg -i boot.img
cd boot
gunzip ramdisk.cpio.gz
mkdir ramdisk
cd ramdisk
#-i --extract 从包中提取文件
#-d --make-directories 需要时创建目录
#-m --preserve-modification-time 创建文件时保留以前文件的修改时间
#-v --verbose 详细列出已处理的文件
cpio -idmv < ../ramdisk.cpio

1.4.2 替换uImage和添加Ramdisk初始化脚本

在上一步的编译结果当中提取uImage内核,kvm 9p virtio等相关内核模块替换掉官方的内核及模块。修改init.mofdv1.rc,让内核能够正确加载相应的模块。lib/modules/modules.order也有保存模块加载的顺序,但好像直接初始化脚本中使用insmod命令就能正确加载内核模块,这个结论是否正确还有待验证。

vim init.mofd_v1.rc
# line 337 add fallowing line
# load up our kvm stuff
insmod /lib/modules/kvm.ko
insmod /lib/modules/kvm-intel.ko
insmod /lib/modules/pci-stub.ko
insmod /lib/modules/font.ko
insmod /lib/modules/sysfillrect.ko
insmod /lib/modules/syscopyarea.ko
insmod /lib/modules/sysimgblt.ko
insmod /lib/modules/fb_sys_fops.ko
insmod /lib/modules/virtio_mmio.ko
insmod /lib/modules/virtio_pci.ko
insmod /lib/modules/virtio_baloon.ko
insmod /lib/modules/virtio_rng.ko
insmod /lib/modules/virtio_console.ko
insmod /lib/modules/virtio_blk.ko
insmod /lib/modules/arizona-i2c.ko
insmod /lib/modules/virtio_net.ko
insmod /lib/modules/vringh.ko
insmod /lib/modules/llc.ko
insmod /lib/modules/bridge.ko
insmod /lib/modules/9pnet.ko
insmod /lib/modules/9pnet_virtio.ko
insmod /lib/modules/9p.ko

1.4.3 打包压缩

zenfone2-boot-tools当中提供了打包脚本,直接拿来用就可以了。为了避免以后不能用,我fork了一份https://github.com/wing-ho/ZenFone2-boot-tools

2 chroot环境下安装docker

如果添加docker-ce的安装源,直接安装docker,dockerd并不能正常运行的,因为Android内核是被裁剪过的,去掉了namespace、cgroup、overylay等内核模块,我试过把这些模块添加到Anroid内核当中,虽然编译成功,但是刷机后,Android系统却无法启动,我又没有相应的手段去调试手机,就只能放弃这种方式,转而使用虚拟机的方式来运行docker。docker-machine就是用来管理docker虚拟机的,默认是使用virtualbox来运行虚拟机的,但是virtualbox在安装过程中需要添加内核模块,Android系统没有提供这种更新内核的机制,内核是存放在独立的boot分区中的,所幸有基于命令行的qemu虚拟机。

2.1 安装docker客户端

2.1.1 方法一

sudo apt-get update 
sudo apt-get install
apt-transport-https \
ca-certificates \
curl \
gnupg2 \
software-properties-common
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add -
sudo add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/debian \
$(lsb_release -cs) \
stable"

sudo apt-get update
sudo apt-get install docker-ce

2.1.2 方法二

curl -fSL -o /tmp/dockerbin.tgz https://download.docker.com/linux/static/edge/x86_64/docker-18.06.0-ce.tgz 
tar -zxvf /tmp/dockerbin.tgz -C ~/usr/bin --strip-components=1
rm /tmp/dockerbin.tgz

2.2 下载docker-machine及qemu驱动

2.2.1 下载docker-machine

sudo curl -fSL -o /usr/local/bin/docker-machine https://github.com/docker/machine/releases/download/v0.15.0/docker-machine-Linux-x86_64

2.2.2 修改qemu驱动

qemu驱动使用9p文件系统来只读挂载一个userdata文件到虚拟机中,我需要把宿主机的/home/$USER挂载到虚拟中对应/home/$USER目录中,因此需要对qemu驱动稍作修改。

git clone https://github.com/machine-drivers/docker-machine-driver-qemu.git
cd docker-machine-driver
sed -i 's/security_model=passthrough,readonly/security_model=none/;s/mount_tag=config-2/mount_tag=user_home/' qemu.go
# 需要自己去配置好go语言的环境
go build cmd -o docker-machine-driver-qemu
chmod +x docker-machine-driver-qemu
sudo cp docker-machine-driver-qemu /usr/local/bin

2.3 创建和配置虚拟机

2.3.1 创建名为default虚拟机

# 解决输入sudo带来的找不到命令的问题
sudo chown wing:wing /usr/bin/qemu-system-x86_64
sudo chown wing:wing /dev/kvm
useradd -a -G docker
# 下载boot2docker镜像
wget https://github.com/boot2docker/boot2docker/releases/download/v18.06.0-ce/boot2docker.iso
docker-machine create -d qemu --qemu-boot2docker-url boot2docker2.iso --qemu-virtio-drives --qemu-display --qemu-display-type vnc=:1 default

2.3.2 配置boot2docker虚拟机

# 配置CloundConfigRoot为宿主机的/home/$USER目录
sed -i 's/"CloudConfigRoot": ""/"CloudConfigRoot": "/home/wing"/' ~/.docker/machine/machines/default/config.json
docker-machine ssh
sudo -s
# 添加自动挂载9p文件系统脚本,粗略测试msize为1M比较合适
cat > /var/lib/boot2docker/bootlocal.sh << EOF
mkdir -p /home/wing
sudo mount -t 9p -o trans=virtio,version=9p2000.L,msize=1048576 user_home /home/wing
EOF
chown +x /var/lib/boot2docker/bootlocal.sh
# 修改docker默认卷驱动和添加国内加速镜像
sed -i 's/DOCKER_STORAGE=aufs/DOCKER_STORAGE=overlay2/;/--label/ a --registry-mirror=https://registry.docker-cn.com' /var/lib/boot2docker/profile
# 重启虚拟机
sudo shutdown
docker-machine start default

3 安装Windows系统

Windows系统并不是我的主力系统,就是用来运行一些Windows环境的软件而已,为了节省空间我选择了xp,目前xp还可以通过posReady补丁持续更新到2019年4月9日。Win7、Win10应该也是能够流畅运行的。让系统流畅的关键是改变cpufreq的模式为ondemand,默认情况下,cpu会在息屏后就会工作在interactive模式下。另外由于GPU驱动的缘故,在虚拟机中看电影,丢帧会比较严重的,视频教程算是勉强可以看的。真的需要看视频可以用Android系统看。下面的是虚拟机启动的脚本:

qemu_args=(
-enable-kvm
-nodefaults
-boot menu=on
-m 2048 -cpu host
-smp 2,sockets=1,cores=2,threads=1
-drive if=virtio,file=$HOME/Machines/winxp.qcow2,media=disk
-cdrom en_windows_xp_professional_with_service_pack_3_x86_cd_vl_x14-73974.iso
# 可以将usb设备直通到虚拟机中
-device nec-usb-xhci,id=xhci
-device usb-host,bus=xhci.0,hostbus=2,hostport=1
-device usb-host,bus=xhci.0,hostbus=3,hostport=1
-localtime
-usb -usbdevice tablet
-vga qxl
-vnc :2
# 在安装系统的时候可以打开vnc,安装和配置好系统之后就下面的选项关闭
#-display none
-monitor telnet:127.0.0.1:2023,server,nowait
-net user,hostfwd=tcp::3389-:3389,smb=$HOME
-net nic,model=virtio
-daemonize
)
qemu-system-x86_64 ${qemu_args[@]}
Last Updated 2018-10-14 日 23:38.
Created by Emacs 25.1.1 (Org mode 9.1.14)