qemu模拟arm最小化文件系统测试记录
-------编译arm内核--------
xy@xydpc:/usr/local/src/linux-4.19.48$
export PATH=$PATH:.:/opt/gcc-linaro-7.4.1-2019.02-x86_64_arm-linux-gnueabi/bin
curl -O http://mirror.lzu.edu.cn/kernel/v4.x/linux-4.19.48.tar.xz
tar Jxf linux-4.19.48.tar.xz
make ARCH=arm help 可以查看支持
make menuconfig ARCH=arm 启动界面配置
如果手工修改了.config文件,可以执行 make ARCH=arm oldconfig加载配置,config.cache缓存文件可以跳过一些验证
make ARCH=arm vexpress_defconfig 利用配置好的模板
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- 编译内核,注意不能省略最后的减号。
xy@xydpc:/usr/local/src/linux-4.19.48$ make modules ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- 编译模块
CALL scripts/checksyscalls.sh
Building modules, stage 2.
MODPOST 6 modules
应该是已经编译过了。
清理 make ARCH=arm clean 或者 make ARCH=arm distclean
-------编译arm文件系统busybox--------
下载文件并编译,用默认配置即可完成编译。
curl -O https://busybox.net/downloads/busybox-1.29.3.tar.bz2 比wget慢
xy@xydpc:/usr/local/src$ tar jxf busybox-1.29.3.tar.bz2
xy@xydpc:/usr/local/src$ cd busybox-1.29.3/
$ make menuconfig 默认几乎没有选中小程序
$ make defconfig 一般选择此命令
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi-
make install 直接生成的_install/bin/busybox是宿主机的ELF文件
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- install
检查了目录,busybox的arch下并不存在arm目录,也看了其他资料,上面的ARCH参数应该是多余的。
下面开始手工创建文件系统
xy@xydpc:~$ dd if=/dev/zero of=~/rfs2.ext bs=1M count=40
xy@xydpc:~$ mkdir ~/rfs
xy@xydpc:~$ mkfs.ext3 ~/rfs.ext
xy@xydpc:~$ sudo mount ~/rfs.ext ~/rfs
xy@xydpc:~$ sudo cp -r /usr/local/src/busybox-1.29.3/_install/* ~/rfs
xy@xydpc:~$ cd ~/rfs
xy@xydpc:~/rfs$ ls
bin linuxrc lost+found sbin usr
xy@xydpc:~/rfs$ sudo mkdir dev etc proc sys tmp
xy@xydpc:~/rfs$ cd dev
xy@xydpc:~/rfs/dev$ sudo mknod -m 660 console c 5 1
xy@xydpc:~/rfs/dev$ sudo mknod -m 660 null c 1 3
xy@xydpc:~/rfs/dev$ cd ../
xy@xydpc:~/rfs$ sudo mkdir etc/init.d
xy@xydpc:~/rfs$ sudo vi etc/init.d/rcS
#! /bin/sh
/bin/mount -a
xy@xydpc:~/rfs$ sudo vi etc/fstab
proc /proc proc defaults 0 0
none /tmp ramfs defaults 0 0
mdev /dev ramfs defaults 0 0
sysfs /sys sysfs defaults 0 0
xy@xydpc:~/rfs$ sudo vi etc/inittab 当时实际未创建该文件
::sysinit:/etc/init.d/rcS
::respawn:-/bin/sh
::restart:/sbin/init
::ctrlaltdel:/bin/umount -a -r
::shutdown:/bin/umount -a -r
::shutdown:/sbin/swapoff –a
xy@xydpc:~/rfs$ sudo vi etc/group
root:*:0:
xy@xydpc:~/rfs$ sudo vi etc/passwd
root::0:0:root:/:/bin/sh
xy@xydpc:~/rfs$ sudo chown -R root:root .
问题1:找不到init文件
VFS: Mounted root (ext3 filesystem) on device 179:0.
Freeing unused kernel memory: 1024K
Run /sbin/init as init process
Run /etc/init as init process
Run /bin/init as init process
Run /bin/sh as init process
Kernel panic - not syncing: No working init found. Try passing init= option to kernel. See Linux Documentation/admin-guide/init.rst for guidance.
检查发现是动态链接的
xy@xydpc:~/rfs/bin$ arm-linux-gnueabi-readelf -d ./busybox
Dynamic section at offset 0xaaf08 contains 26 entries:
标记 类型 名称/值
0x00000001 (NEEDED) 共享库:[libm.so.6]
0x00000001 (NEEDED) 共享库:[libresolv.so.2]
0x00000001 (NEEDED) 共享库:[libc.so.6]
xy@xydpc:~/rfs$ cd /opt/gcc-linaro-7.4.1-2019.02-x86_64_arm-linux-gnueabi/lib/
xy@xydpc:/opt/gcc-linaro-7.4.1-2019.02-x86_64_arm-linux-gnueabi$ sudo cp ./arm-linux-gnueabi/libc/lib/libm-2.25.so ~/rfs/lib
xy@xydpc:~/rfs/lib$ sudo ln -s libm-2.25.so libm.so.6
空间不足了,继续折腾,库文件比较大,测试了放在目录/lib或者/bin都是不可行的,因为此时init也是到busybox的链接,init本身都还没有加载,无法具备加载链接库文件的功能。
$ dd if=/dev/zero of=~/rfs2.ext bs=1M count=40
$ mkfs.ext3 ~/rfs2.ext
$ sudo umount ~/rfs
$ sudo mount ~/rfs.ext /mnt
$ sudo mount ~/rfs2.ext ~/rfs
$ sudo cp -rp /mnt/* ~/rfs
cd /opt/gcc-linaro-7.4.1-2019.02-x86_64_arm-linux-gnueabi/arm-linux-gnueabi/libc/lib
sudo cp libm-2.25.so ~/rfs/lib
sudo cp libc-2.25.so ~/rfs/lib
sudo cp libresolv-2.25.so ~/rfs/lib
xy@xydpc:~/rfs/lib$ sudo ln -s libc-2.25.so libc.so.6
xy@xydpc:~/rfs/lib$ sudo ln -s libm-2.25.so libm.so.6
xy@xydpc:~/rfs/lib$ sudo ln -s libresolv-2.25.so libresolv.so.2
重新编译为静态文件
$ make defconfig
Settings ---> --- Build Options
[*] Build static binary (no shared libs)
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi-
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- install
xy@xydpc:/usr/local/src/busybox-1.29.3/_install/bin$ file busybox
busybox: ELF 32-bit LSB executable, ARM, EABI5 version 1 (GNU/Linux), statically linked, for GNU/Linux 3.2.0, BuildID[sha1]=cb8df546bfd3e37b86def4cdd3dffc9e586d795e, stripped
xy@xydpc:/usr/local/src/busybox-1.29.3/_install$ sudo cp -r * ~/rfs/
xy@xydpc:~/rfs/bin$ arm-linux-gnueabi-readelf -d busybox
There is no dynamic section in this file.
新报错:rcS权限及tty文件不存在问题
can’t run ‘/etc/init.d/rcS’: Permission denied
can’t open /dev/tty4: No such file or directory
方法
xy@xydpc:~/rfs$ sudo chmod 744 etc/init.d/rcS
xy@xydpc:~/rfs$ sudo mknod dev/tty1 c 4 1
xy@xydpc:~/rfs$ sudo mknod dev/tty2 c 4 2
xy@xydpc:~/rfs$ sudo mknod dev/tty3 c 4 3
xy@xydpc:~/rfs$ sudo mknod dev/tty4 c 4 4
没有作用,sudo mv rcS bak.rcS后可以进入命令行。
恢复rcS,增加inittab文件后可以进入命令行。但是df发现都没有挂载文件系统。
找不到的tty的错误原因是:参考root@xydpc:/usr/local/src/busybox-1.29.3/examples# vi inittab的解释,当未指定inittab时,默认的配置包含了tty2/3/4
# Note: BusyBox init works just fine without an inittab. If no inittab is
# found, it has the following default behavior:
# ::sysinit:/etc/init.d/rcS
# ::askfirst:/bin/sh
# ::ctrlaltdel:/sbin/reboot
# ::shutdown:/sbin/swapoff -a
# ::shutdown:/bin/umount -a -r
# ::restart:/sbin/init
# tty2::askfirst:/bin/sh
# tty3::askfirst:/bin/sh
# tty4::askfirst:/bin/sh
找不到tty的问题2:修改inittab配置
之前做的那个busybox,也是报错找不到tty,去掉tty2::askfirst:-/bin/sh前面的tty2后解决。
报错找不到null设备的,但回车可以进入命令行,注释掉这一行 ::respawn:/sbin/getty -L ttyAMA0 115200 xterm
修改后的文件如下,也可以正常进入了。
[root@(none) etc]# cat inittab
::sysinit:/etc/init.d/rcS
#::respawn:/sbin/getty -L ttyAMA0 115200 xterm
#::respawn:-/bin/sh
::askfirst:-/bin/sh
::ctrlaltdel:/bin/umount -a -r
::shutdown:/bin/umount -a -r
::shutdown:/sbin/swapoff -a
[root@(none) etc]#
注意检查inittab文件的一些中文字符,重启后正常。
EXT4-fs (mmcblk0): mounting ext3 file system using the ext4 subsystem
random: fast init done
EXT4-fs (mmcblk0): warning: mounting fs with errors, running e2fsck is recommended
EXT4-fs (mmcblk0): mounted filesystem with ordered data mode. Opts: (null)
VFS: Mounted root (ext3 filesystem) on device 179:0.
Freeing unused kernel memory: 1024K
Run /sbin/init as init process
random: crng init done
/bin/sh: can't access tty; job control turned off 这里仍然有个报错
~ # df
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/root 45478 21981 20937 51% /
~ # cat /proc/cpuinfo
processor : 0
model name : ARMv7 Processor rev 0 (v7l)
BogoMIPS : 508.72
Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpd32
CPU implementer : 0x41
CPU architecture: 7
CPU variant : 0x0
CPU part : 0xc09
CPU revision : 0
Hardware : ARM-Versatile Express
Revision : 0000
Serial : 0000000000000000
~ # ls /sys/devices/
armv7_cortex_a9 platform system uprobe
breakpoint software tracepoint virtual
~ #
正确情况inittab是有减号的,表示需要进行交互,也就是需要按一下回车键。
::respawn:-/bin/sh
/dev目录为空的问题
启动后发现找不到手动在rfs.ext3文件系统中创建的文件,注释掉etc/fstab中的行
#mdev /dev ramfs defaults 0 0
重启后问题解决。
验证mdev加载问题
参考资料 mdev详解
移走/dev下的文件,启动日志
EXT4-fs (mmcblk0): mounting ext3 file system using the ext4 subsystem
random: fast init done
EXT4-fs (mmcblk0): warning: mounting fs with errors, running e2fsck is recommended
EXT4-fs (mmcblk0): mounted filesystem with ordered data mode. Opts: (null)
VFS: Mounted root (ext3 filesystem) on device 179:0.
Freeing unused kernel memory: 1024K
Run /sbin/init as init process
random: crng init done
检查启动情况
~ # mount
/dev/root on / type ext3 (rw,relatime)
proc on /proc type proc (rw,relatime)
none on /tmp type ramfs (rw,relatime)
sysfs on /sys type sysfs (rw,relatime)
~ # ls /dev
bb
~ # cat /etc/fstab
proc /proc proc defaults 0 0
none /tmp ramfs defaults 0 0
#mdev /dev ramfs defaults 0 0
sysfs /sys sysfs defaults 0 0
手动挂载mdev,/dev并无变化,仍然为空
~ # mount -t ramfs mdev /dev
~ # mount
/dev/root on / type ext3 (rw,relatime)
proc on /proc type proc (rw,relatime)
none on /tmp type ramfs (rw,relatime)
sysfs on /sys type sysfs (rw,relatime)
mdev on /dev type ramfs (rw,relatime)
~ # ls /dev
~ #
执行mdev -s命令,自动生成多个设备文件。如果需要可以写入到rcS脚本。
~ # mdev -s
~ # ls /dev
console tty1 tty52
...
对之前的~/armroot/a9rootfs.ext3文件系统再次测试:
[root@(none) ~]# cat /etc/fstab
proc /proc proc defaults 0 0
none /tmp ramfs defaults 0 0
#mdev /dev ramfs defaults 0 0 //去掉mdev的挂载
sysfs /sys sysfs defaults 0 0
[root@(none) ~]# vi /etc/inittab
[root@(none) ~]# cat /etc/inittab
::sysinit:/etc/init.d/rcS
::respawn:/sbin/getty -L ttyAMA0 115200 xterm 去掉注释
#::respawn:-/bin/sh
::askfirst:-/bin/sh
::ctrlaltdel:/bin/umount -a -r
::shutdown:/bin/umount -a -r
::shutdown:/sbin/swapoff -a
[root@(none) ~]#
[root@(none) ~]# cat /etc/init.d/rcS 保持不变
#! /bin/sh
/bin/mount -a
[root@(none) ~]# reboot
重启后运行正常,日志如下:
EXT4-fs (mmcblk0): mounting ext3 file system using the ext4 subsystem
random: fast init done
EXT4-fs (mmcblk0): mounted filesystem with ordered data mode. Opts: (null)
VFS: Mounted root (ext3 filesystem) on device 179:0.
Freeing unused kernel memory: 1024K
Run /sbin/init as init process
random: crng init done
Please press Enter to activate this console.
MiniRoot FileSystem is Ready ...
[root@(none) ~]#
[root@(none) ~]# exit
Please press Enter to activate this console.
MiniRoot FileSystem is Ready ...
[root@(none) ~]# exit
Please press Enter to activate this console.
MiniRoot FileSystem is Ready ...
[root@(none) ~]# shutdown -h now
-/bin/sh: shutdown: not found
[root@(none) ~]#
根目录问题
前面的启动日志有报错:
EXT4-fs (mmcblk0): warning: mounting fs with errors, running e2fsck is recommended
运行一段时间会出现下面的提示
EXT4-fs (mmcblk0): error count since last fsck: 4
EXT4-fs (mmcblk0): initial error at time 1559970622: ext4_mb_generate_buddy:757
EXT4-fs (mmcblk0): last error at time 1560036552: ext4_mb_generate_buddy:747
关闭目标机器,在宿主机修复文件系统
xy@xydpc:~$ sudo e2fsck ./rfs.ext
重启没有报错(观察了约10分钟)。
虚拟机不能shutdown,只能关闭窗口,关闭前执行sync。关闭窗口启动日志没有再报错。
整个文件系统很小,不到3M,还有网卡可配置
~ # uname -a
Linux (none) 4.19.48 #1 SMP Fri Jun 7 16:16:47 CST 2019 armv7l GNU/Linux
~ # df -h
Filesystem Size Used Available Use% Mounted on
/dev/root 44.4M 2.7M 39.2M 6% /
~ # ip addr add 192.168.199.223/24 dev eth0
~ # ip ad
1: lo: <LOOPBACK> mtu 65536 qdisc noop qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop qlen 1000
link/ether 52:54:00:12:34:56 brd ff:ff:ff:ff:ff:ff
inet 192.168.199.223/24 scope global eth0
valid_lft forever preferred_lft forever
~ #
ping不通主机,qemu-system-arm不了解怎么配置互联。
-------qemu模拟--------
qemu-system-arm -M vexpress-a9 -m 512M -dtb /usr/local/src/linux-4.19.48/arch/arm/boot/dts/vexpress-v2p-ca9.dtb -kernel /usr/local/src/linux-4.19.48/arch/arm/boot/zImage -nographic -append “root=/dev/mmcblk0 rw console=ttyAMA0” -sd ~/rfs.ext
图形化运行正常
xy@xydpc:~/armroot/rfs1$ qemu-system-arm -M vexpress-a9 -m 512M -dtb vexpress-v2p-ca9.dtb -kernel zImage -append "root=/dev/mmcblk0 rw " -sd a9rootfs.ext3
更换根正常
xy@xydpc:~/armroot/rfs1$ qemu-system-arm -M vexpress-a9 -m 512M -dtb vexpress-v2p-ca9.dtb -kernel zImage -append "root=/dev/mmcblk0 rw " -sd …/rfs.ext
但更换内核就弹出黑色图形窗口,权限也一样了
xy@xydpc:~/armroot$ sudo chown libvirt-qemu:kvm zImage rfs.ext vexpress-v2p-ca9.dtb
sudo chmod 666 rfs.ext
xy@xydpc:~/armroot/rfs1$ qemu-system-arm -M vexpress-a9 -m 512M -dtb …/vexpress-v2p-ca9.dtb -kernel …/zImage -append "root=/dev/mmcblk0 rw " -sd …/rfs.ext
看来和内核配置有关。
-------内核补丁-看书笔记--------
make ARCH=arm distclean
创建补丁 diff -Naurp kernel-tree kernel-source > patch.file
检查补丁 ./kernel-source/checkpatch.pl
测试补丁 patch -p1 --dry-run < /path/to/patch.file
应用补丁 patch -p1 < /path/to/patch.file
-------常用开源软件-看书笔记--------
DirectFB图形库
Dropbear ssh2软件,含服务器和客户端
QT 图形化环境
JamVM JAVA虚拟机
Rzsz x/z-modem串口传输文件
netcat 管道收发数据,支持shell
tinyxml 解析xml
micro_httpd http服务器
tupid-ftpd ftp服务器
quagga 路由软件
tslib 触摸屏接口
fgetty tty登录
性能分析工具 gprof 编译时增加 -g -pg选项
内存泄漏检测工具 dmalloc mpatrol 静态工具 splint
-------挂载mtdram--------
# ls -l /proc/mtd
-r--r--r-- 1 root root 0 Jan 1 02:05 /proc/mtd
# cat /proc/mtd
dev: size erasesize name
# ls -l /dev/mt*
ls: /dev/mt*: No such file or directory
# modprobe mtdram total_size=65536 erase_size=128
modprobe: can't open 'modules.dep': No such file or directory
#
在机顶盒无法加载模块mtdram,对应软件包 mtd-tools
在台式机查看
$ lsmod |grep mtdram
mtdram 16384 0
mtd 57344 5 mtdram,cmdlinepart,jffs2,cramfs
#modprobe mtdram total_size=65536 erase_size=128
$cat /proc/mtd
dev: size erasesize name
mtd0: 04000000 00020000 "mtdram test device"
# dd if=rootfs.jffs2 of=/dev/mtdblock0 书上的这个文件,实际不存在
# mount -t jffs2 /dev/mtd0 /mnt/ 书上挂载的又是mtd0
小结
整个文件系统很小,不到3M,内核4M,还有网卡可配置;最小内存32M可启动,笔记本电脑(Intel® Core™ i5-5200U CPU @ 2.20GHz)虚拟时的时间不到5秒。
折腾了好几天,问题基本上解决了,基本上理解了内核和文件系统,但是bootloader还是未能进行验证。
从网络上找的配置,其中fstab的/dev挂载是个大坑,覆盖掉了原有的/dev文件,而且也没有自动生成。