Yocto构建只读文件系统
嵌入式调试过程中,mount命令发现系统分区是只读的,不利于开发阶段的调试,例如想单独安装调试软件都不行。
/dev/mmcblk0p5 on / type ext4 (ro,relatime)
于是想让系统变为rw支持读写的,条条大路通罗马,Linux世界里要实现一个功能有N个方法,系统是否只读可以由多个因素决定,如:
1. 文件系统的类型,例如squashfs文件系统就是一个压缩只读的文件系统,如果系统采用squashfs文件系统的话,那么系统起来后是不能写的
2. /etc/fstab中指定分区的读写类型
例如下例中系统根目录是只读的,不能写
cat /etc/fstab # stock fstab - you probably want to override this with a machine specific one /dev/root / auto ro 0 0
那么在Yocto系统如何修改fstab控制系统各个分区的读写属性呢?
以我的Yocto版本为例,其中有一个base-files_3.0.14.bb,会设置系统的fstab,这里默认是读写属性,如果想设置自己的系统为只读,可以创建对应的base-files_3.0.14.bbappend在其中对fstab修改,
但是我的例子中分析完base-files相关的recipe后发现他们没有修改为只读属性。于是如下命令查找所有layers下的对fstab相关的bb文件
find layers/ -type f -name "*bb*" -exec grep -H fstab {} \;
发现layers/oe-core/meta/classes/rootfs-postcommands.bbclass中的read_only_rootfs_hook函数有对读写属性操作。
进一步跟踪定位发现,所以IMAGE_FEATURES如果设置为read-only-rootfs那么fstab中将设置为只读。
# Tweak the mount options for rootfs in /etc/fstab if read-only-rootfs is enabled ROOTFS_POSTPROCESS_COMMAND += '${@bb.utils.contains("IMAGE_FEATURES", "read-only-rootfs", "read_only_rootfs_hook; ", "",d)}'
接下来就好说了,查看recipe中设置IMAGE_FEATURES的地方就好了。
BTW: 由read_only_rootfs_hook实现来看,不同的系统只读设置是有很多可能的,详情参照read_only_rootfs_hook。
FYI:read_only_rootfs_hook函数
#
# A hook function to support read-only-rootfs IMAGE_FEATURES
#
read_only_rootfs_hook () {
# Tweak the mount option and fs_passno for rootfs in fstab
if [ -f ${IMAGE_ROOTFS}/etc/fstab ]; then
sed -i -e '/^[#[:space:]]*\/dev\/root/{s/defaults/ro/;s/\([[:space:]]*[[:digit:]]\)\([[:space:]]*\)[[:digit:]]$/\1\20/}' ${IMAGE_ROOTFS}/etc/fstab
fi
# Tweak the "mount -o remount,rw /" command in busybox-inittab inittab
if [ -f ${IMAGE_ROOTFS}/etc/inittab ]; then
sed -i 's|/bin/mount -o remount,rw /|/bin/mount -o remount,ro /|' ${IMAGE_ROOTFS}/etc/inittab
fi
# If we're using openssh and the /etc/ssh directory has no pre-generated keys,
# we should configure openssh to use the configuration file /etc/ssh/sshd_config_readonly
# and the keys under /var/run/ssh.
if [ -d ${IMAGE_ROOTFS}/etc/ssh ]; then
if [ -e ${IMAGE_ROOTFS}/etc/ssh/ssh_host_rsa_key ]; then
echo "SYSCONFDIR=\${SYSCONFDIR:-/etc/ssh}" >> ${IMAGE_ROOTFS}/etc/default/ssh
echo "SSHD_OPTS=" >> ${IMAGE_ROOTFS}/etc/default/ssh
else
echo "SYSCONFDIR=\${SYSCONFDIR:-/var/run/ssh}" >> ${IMAGE_ROOTFS}/etc/default/ssh
echo "SSHD_OPTS='-f /etc/ssh/sshd_config_readonly'" >> ${IMAGE_ROOTFS}/etc/default/ssh
fi
fi
# Also tweak the key location for dropbear in the same way.
if [ -d ${IMAGE_ROOTFS}/etc/dropbear ]; then
if [ ! -e ${IMAGE_ROOTFS}/etc/dropbear/dropbear_rsa_host_key ]; then
echo "DROPBEAR_RSAKEY_DIR=/var/lib/dropbear" >> ${IMAGE_ROOTFS}/etc/default/dropbear
fi
fi
if ${@bb.utils.contains("DISTRO_FEATURES", "sysvinit", "true", "false", d)}; then
# Change the value of ROOTFS_READ_ONLY in /etc/default/rcS to yes
if [ -e ${IMAGE_ROOTFS}/etc/default/rcS ]; then
sed -i 's/ROOTFS_READ_ONLY=no/ROOTFS_READ_ONLY=yes/' ${IMAGE_ROOTFS}/etc/default/rcS
fi
# Run populate-volatile.sh at rootfs time to set up basic files