以下技术在盈鹏飞嵌入式的A40I/T3核心板(CoM-X40I)和主控板(SBC-X40I)上经过验证,欢迎 交流! CoM-X40I核心板和SBC-X40I主板见下图:
1. 前言
由于场景需求,需要切换不同的rootfs进行挂载;
如下记录了调试过程
2. chroot 切换原理
Linux 3.4版本内核支持chroot系统调用,
chroot可以改变进程froot directory 到新的文件系统挂载路径,
current->fs->root = { new path,包含root vfsmount和root dentry}。
busybox工具包支持chroot shell命令:
-
chroot
[OPTION] NEWROOT
[COMMAND [ARG]...]
-
chroot OPTION
-
NEWROOT: 切换到新的root目录,在新的root目录下执行命令
3.adb shell rootfs切换
(1)获取rootfs2烧录文件
lichee编译linux方案,拷贝lichee/out/sun8iw7p1/linux/common/rootfs.ext4,
将拷贝后的rootfs.ext4重命名为rootfs2.ext4
{注:lichee/out/sun8iw7p1/linux/common/buildroot/target目录下放着rootfs.ext4原文件和目录}。
lichee编译android方案,将rootfs2.ext4文件拷贝到lichee/out/sun8iw7p1/android/common/目录下。
(2) 添加rootfs2分区
修改lichee/tools目录下pack文件和方案对应的sys_partition.fex文件,添加rootfs2分区。
-
diff --git a/pack/chips/sun8iw7p1/configs/dolphin-p2/sys_partition.fex b/pack/chips/sun8iw7p1/configs/-
-
-dolphin-p2/sys_partition.fex
-
index e3453e5..2890a09 100755
-
--- a/pack/chips/sun8iw7p1/configs/dolphin-p2/sys_partition.fex
-
+++ b/pack/chips/sun8iw7p1/configs/dolphin-p2/sys_partition.fex
-
@@ -89,6 +89,14 @@ size = 16384
-
keydata = 1
-
user_type = 0x8000
-
+;------------------------------> mmcblk0p10/nandg
-
+[partition]
-
+ name = rootfs2
-
+ size = 286720
-
+ downloadfile = "rootfs2.fex"
-
+ keydata = 1
-
+ user_type = 0x8000
-
+
-
;------------------------------> mmcblk0p11/nandh
-
[partition]
-
name = Reserve0
-
diff --git a/pack/pack b/pack/pack
-
index 4a2afde..a199b5a 100755
-
--- a/pack/pack
-
+++ b/pack/pack
-
@@ -599,6 +599,7 @@ function do_pack_android()
-
ln -s ${ANDROID_IMAGE_OUT}/boot.img boot.fex
-
ln -s ${ANDROID_IMAGE_OUT}/system.img system.fex
-
ln -s ${ANDROID_IMAGE_OUT}/recovery.img recovery.fex
-
+ ln -s ${LICHEE_OUT}/rootfs2.ext4 rootfs2.fex
(3) 手动挂载rootfs2分区
调试主板烧录android方案固件,系统启动初始化后,
查看block块与分区的映射关系,检查rootfs分区块设备是否已经创建,
如下蓝色标示所示。
-
# ls -l /dev/block/by-name
-
lrwxrwxrwx root root
1970-
01-
01
08:
00 Reserve0 ->
/dev/block
/nandi
-
lrwxrwxrwx root root 1970-01-01 08:00 Reserve1 -> /dev
/block/nandk
-
lrwxrwxrwx root root
1970-
01-
01
08:
00 Reserve2 ->
/dev/block
/nandl
-
lrwxrwxrwx root root 1970-01-01 08:00 UDISK -> /dev
/block/nandn
-
lrwxrwxrwx root root
1970-
01-
01
08:
00 boot ->
/dev/block
/nandc
-
lrwxrwxrwx root root 1970-01-01 08:00 bootloader -> /dev
/block/nanda
-
lrwxrwxrwx root root
1970-
01-
01
08:
00 cache ->
/dev/block
/nandm
-
lrwxrwxrwx root root 1970-01-01 08:00 env -> /dev
/block/nandb
-
lrwxrwxrwx root root
1970-
01-
01
08:
00 klog ->
/dev/block
/nandj
-
lrwxrwxrwx root root 1970-01-01 08:00 misc -> /dev
/block/nande
-
lrwxrwxrwx root root
1970-
01-
01
08:
00
private ->
/dev/block
/nandg
-
lrwxrwxrwx root root 1970-01-01 08:00 recovery -> /dev
/block/nandf
-
lrwxrwxrwx root root
1970-
01-
01
08:
00 rootfs2 ->
/dev/block
/nandh
-
lrwxrwxrwx root root 1970-01-01 08:00 system -> /dev
/block/nandd
rootfs2 分区对应block设备创建成功后,通过adb工具执行以下命令进行手动挂载rootfs2分区:
-
adb shell e2fsck -y
/dev/block/nandh
-
-
adb 控制台打印如下:
-
e2fsck
1.41
.14 (
22-Dec
-2010)
-
/dev/block
/nandh: clean, 996/
7168 files,
24876/
28672 blocks
mkdir /mnt/tmps mount -o rw,noatime,nosuid,nodev,nomblk_io_submit,barrier=1,noauto_da_alloc -t ext4 /dev/block/nandh /mnt/tmps
-
adb 控制台打印如下:
-
root
@dolphin-fvd-
p1:/
# mount
-
.... ...
-
/dev/block
/nandh /mnt
/tmps ext4 rw,nosuid,nodev,noatime,nomblk_io_submit,noauto_da_alloc,data=ordered 0 0
-
... ....
-
# ls -l /mnt
/tmps
-
-rwxr-xr-x root root 2809 2016-07-28 15:21 autorun.sh
-
drwxr-xr-x root root 2012-09-26 15:20 bin
-
drwxr-xr-x root root 2012-07-02 16:21 dev
-
drwxr-xr-x root root 2016-07-28 15:21 dragonboard
-
drwxr-xr-x root root 2014-03-15 20:26 etc
-
drwxr-xr-x root root 2012-07-02 16:21 home
-
lrwxrwxrwx root root 2012-07-02 16:21 init -> bin/busybox
-
drwxr-xr-x root root
2016-
07-
28
15:
21
lib
-
lrwxrwxrwx root root
2012-
07-
02
16:
21 linuxrc -> bin/busybox
-
drwxr-xr-x root root
2012-
07-
02
16:
21 mnt
-
drwxr-xr-x root root
2012-
07-
02
16:
21 opt
-
drwxr-xr-x root root
2012-
07-
02
16:
21 proc
-
drwxr-xr-x root root
2012-
07-
02
16:
21 root
-
drwxr-xr-x root root
2012-
07-
02
16:
21 sbin
-
drwxr-xr-x root root
2012-
07-
02
16:
21 sys
-
drwxr-xr-x root root
2012-
07-
02
16:
21 tmp
-
drwxr-xr-x root root
2012-
07-
02
16:
21 usr
-
drwxr-xr-x root root
2012-
07-
02
16:
21 var
(4) adb shell手动切换 / 目录
-
chmod 777 /mnt/tmps/bin busybox-smp
-
-
chroot /mnt/tmps /bin/busybox
-
-
mount -t proc newproc /proc
-
-
busybox-smp
-
-
chroot /mnt/tmps /bin/busybox
-
-
cat /proc/self/mountinfo
将当前adb shell 进程rootfs / 目录切换到/mnt/tmps挂载路径,挂载proc文件系统到新的 / 目录下,并重命名newproc,最后通过cat /proc/self/mountstats 命令打印出adb shell空间mountinfo 信息,查看rootfs是否切换成功。
命令执行后,从adb控制台打印可以看到adb shell进程空间的 / 目录已经切换到/dev/block/nandh块设备对应的挂载分区,且newproc挂载在当前进程空间的 /proc 路径。
-
adb 控制台打印如下:
-
292
1
93:
56 / / rw,nosuid,nodev,noatime shared:
19 - ext4 /dev/block/nandh -
-
-rw,nomblk_io_submit,noauto_da_alloc,errors=remount-ro,
data=ordered
-
512
292
0:
3 / /
proc rw,relatime shared:
20 -
proc newproc rw
为了进一步证明adb shell rootfs已经切换成功,
此时通过console shell执行命令: cat /proc/self/mountstats 命令执行后,
从console 控制台打印可以看到,/dev/block/nandh块设备已经成功挂载在系统/mnt/tmps 目录下,而newproc挂载到了/mnt/tmps/proc目录下,
说明adb shell rootfs切换成功。
-
console 控制台打印如下:
-
.... ..... ....
-
292
1
93:
56 /
/mnt/tmps rw,nosuid,nodev,noatime
shared:
19 - ext4 /dev/block/nandh-
-
-rw,nomblk_io_submit,noauto_da_alloc,errors=remount-ro,data=ordered
-
512
292
0:
3 /
/mnt/tmps/proc rw,relatime
shared:
20 - proc newproc rw
-
.... ..... ....
4. android init rootfs切换
参照实验操作细节,准备以下实验条件和步骤:
(1) 添加rootfs2分区
(2) 修改android init代码,添加切换rootfs代码
-
--- a/init/boostup.c
-
+++ b/init/boostup.c
-
@@ -726,6 +726,13 @@ static int aw_media_karaok_boost_cpus(int pid, int index)
-
active = 0;
-
}
-
+ B_LOG("\n\n ++++++++++++ boost pid %d changeroot\n",getpid());
-
+ if (execl("/system/bin/busybox-smp", "/system/bin/busybox-smp", "chroot",
-
+ "/mnt/tmps", "/bin/busybox", "init", NULL)) {
-
+ ERROR("pid%d start exec failed %s \n", getpid(), strerror(errno));
-
+ }
(3) 编译、烧录android固件和启动android系统
(4)手动挂载rootfs2分区, 修改rootfs2分区/bin目录和/sbin目录下的文件可执行权限
(5) 发送init rootfs切换命令
setprop media.boost.pref modem1:2
发送完命令后,android init进程首先通过chroot命令将进程的rootfs切换到/mnt/tmps分区,
然后通过exec命令加载/mnt/tmps/bin/busybo ELF可执行文件,最后执行busybox init。
注意:此处的init rootfs切换只是初步试验,由于busybox init过程会涉及解析initab,挂载分区等操作,所以android init 直接切换到linux小系统的busybox init不会执行完整过程。
接下来需要验证android init进程切换rootfs后,进程状态会发生哪些变化.
a. 系统Init进程名发生变化 通过adb shell ps-p命查看系统init进程名称已经变更成/bin/busybox,如下:
b. 系统console控制台发生变化 通过串口console 控制台可以看到linux小系统登录的shell界面,
c. 系统init进程信息变化 通过adb shell cd /proc/1 命令切换到系统init进程在/proc debug目录,
查看切换后的init进程状态变化,如下,系统init进程cwd对应到/mnt/tmps目录,
运行的ELF文件对应到exec /mnt/tmps/bin/busybox可执行文件,
root目录指向root -> /mnt/tmps 目录。
adb shell debuggerd命令查看系统init进程backtrace
adb shell 命令查看系统init进程mountinfo信息,/目录切换到/dev/block/nandh块设备区