Linux 嵌入式系统启动
前言
一直很好奇嵌入式linux是的启动流程,以前是做芯片的,对单纯芯片的启动非常熟悉,现在的工作基本在user space,现在回过头来研究下底层的启动。
了解完整的linux启动过程,可以看看linux引导过程内幕,很详细。
另外一直以来对项目的基于squash文件系统的ota升级颗粒度过大颇有微词,看看能否有改进之处。
bin打包
- bin打包时,指定了烧录的的地址分区
注意这些分区文件都是按squashfs
or yaffs2
文件系统制作好的,并且在制作bin之前进行压缩以节省空间。
../tools/bin/isp pack_image ../ISPBOOOT.BIN \
xboot0 uboot0 \
xboot1 0x0060000 \
uboot1 0x0060000 \
uboot2 0x0060000 \
env 0x0020000 \
env_redund 0x0020000 \
ecos 0x0300000 \
kernel 0x0260000 \
rootfs 0x0600000 \
pq 0x0020000 \
tcon 0x0020000 \
iop_car 0x0020000 \
runtime_cfg 0x0020000 \
version_info 0x0020000 \
vendordata 0x0020000 \
logo 0x0480000 \
isp_logo 0x0500000 \
kvdb 0x2000000 \
system 0x3000000 \
spsdk 0x1000000 \
leavn 0x3000000 \
nvm 0x8200000 \
update 0xC800000 \
vd_restore 0x0040000
uboot启动
略..
load kernel
略…
load rootfs
init进程
-
这个分区值最终在启动后,在/proc/mtd里体现
-
init进程 /etc/inittab
init进程都是知道是程序的第1个启动程序,它将根据/etc/inittab文件来创建其他的子进程,比如调用脚本文件配置IP地址,挂载其他的文件系统,最后启动shell等。
# Start an "respawn" shell on the serial port
ttyS0::respawn:-/bin/sh
#ttyS0::askfirst:-/bin/ash
# Stuff to do when restarting the init process
::restart:/sbin/init
# Stuff to do before rebooting
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r
::shutdown:/sbin/swapoff -a
etc/init.d/rcS分析
该脚本是如何执行的还待分析,仅知道肯定是初始启动的脚本。
- 启动脚本里 etc/init.d/rcS 挂载mtd的文件到工作目录
对应了前面的flash烧写的内容
system_mtdid=`cat /proc/mtd | grep system | sed "s/:.*//" | sed "s/mtd//"`
...
#/ota/system 是只读的, squashfs文件系统
mount -t squashfs /dev/blockrom$system_mtdid /ota/system
- 还有几个目录是按
yaffs2
文件系统挂载的,应该是可读写的
mount -t yaffs2 -o noatime /dev/mtdblock$nvm_mtdid /data
- 如果检测到有更新,即存在reinstall_file文件,则执行更新
这里应该就是ota升级的诀窍
if [ -f /update/reinstall_file ];then
cd /update
rows=`ls -l *.squash |awk 'END{print NR}'`
cols=`ls -l *.squash |awk 'END{print NF}'` #need to test!!!
[ $rows -eq 0 -o $cols -eq 0 ] && echo "Not Found Any Squash File, Check Update Or Not!"
for i in $(seq 1 $rows)
do
FILENAME=`ls -l *.squash | sed -n "${i}p" | awk '{print $NF}'`
PARTITION=`echo $FILENAME | sed "s/\..*//"`
MOUNTPOINT=$PARTITION
if [ -f /ota/$MOUNTPOINT/install.sh ];then
/ota/$MOUNTPOINT/install.sh
fi
done
rm -f /update/reinstall_file
cd -
fi
- 执行应用层的启动脚本
/tdGUI/start.sh
start.sh
这个启动层脚本 初略看下把
- 运行了某个install.sh脚本的某个命令
其核心效果就是创建从目录a到目录b的软链接。 前面提到文件挂载其实就是在目录b(/ota/leavn..),而软链接全部在/data/usr/下 方便统一管理。
do_merge_dir: link /data/usr/bin/AndroidPhone --> /ota/leavn/package/LeAVN/bin/AndroidPhone
- 加载硬件厂家负责的驱动
有MCU,驱动屏的。
insmod /ota/spsdk/drivers/i2c-core.ko
insmod /ota/spsdk/drivers/i2c-gemini.ko
insmod /ota/spsdk/drivers/i2c-dev.ko
insmod /ota/spsdk/drivers/evdev.ko
insmod /ota/spsdk/drivers/gt9xx.ko
- 运行了一个应用程序管理器,其实也就是把之前统一管理的
app
,按需求启动起来,
直接用service systemctrl不就好? 比如按顺序启动了这些程序
"aaa"
"bbb"
"ccc"
"ddd"
- 启动udev
管理热拔插的
- 初始化 bsp sdk.sh
主要工作即export各种库的路径,加载各种usb sd 声卡的驱动等等。
总结
大概的启动流程其实和标准linux并无二致。从中看出squash文件如果要修改颗粒度:
- 思路1
传输原始文件,颗粒度小 但是要按实际的文件组织形式,再车机上打包squash、 问题在于车机打包,将会很慢很慢。
- 思路2
在最开始分区的时候就细分?