这里我就PXA的代码为例,说下Android系统是如何起来的,特别是Android启动的第一个进程,init进程是如何启动的。
首先uboot会通过bootargs把rdinit的所在路径传递给kernel-->
run_command("setenv bootargs rdinit=/busybox/rdinit cpmem=16M reserve_pmem=0x3000000 comm_v75 android uart_dma", 0);
可以看到红色部分即需要传递的路径地址,然而rdinit是什么呢,这里先简单说下所谓rdinit其实就是一个板级相关的脚本,里面会决定从哪启动ramdisk?nfs?mmc?等等,
那么好我们接下来看kernel里接收这个参数的函数,所在文件kernel/init/main.c
static int __init rdinit_setup(char *str)
{
unsigned int i;
ramdisk_execute_command = str;
/* See "auto" comment in init_setup */
for (i = 1; i < MAX_INIT_ARGS; i++)
argv_init[i] = NULL;
return 1;
}
__setup("rdinit=", rdinit_setup);
内核会把路径传递给全局变量ramdisk_execute_command,并通过
sys_access((const char __user *) ramdisk_execute_command, 0)函数执行rdinit脚本,脚本里会执行rootfs下的init,而这个init是android里的用户程序,位置在system/core/init/init.c
下面我们来简单讲下rdinit脚本,以PXA的这份rdinit为例,它做了这么几件事
1. rdinit_prepare,这个函数里主要为init进程启动作准备,mount proc sysfs等工作
2. 根据dev来判断从哪里启动,
for dev in $ROOTFS_DEV ; do
if [ "$dev" = "flash" ]; then
try_boot_from_ramdisk $INIT_MTDBLK
continue
fi
if [ "$dev" = "nfs" ]; then
if try_prepare_network ; then
for type in $ROOTFS_TYPE ; do
if [ "$type" = "android" ]; then
try_boot_from_android_nfs
fi
if [ "$type" = "generic" ]; then
try_boot_from_rootfs_nfs
fi
done
fi
fi
if [ "$dev" = "mmc0" ]; then
try_boot_from_ramdisk "$INIT_MMCBLK"0
if [ $? = 0 ]; then
try_boot_from_mmc 0
fi
continue
fi
if [ "$dev" = "mmc1" ]; then
try_boot_from_ramdisk "$INIT_MMCBLK"1
if [ $? = 0 ]; then
try_boot_from_mmc 1
fi
continue
fi
done
接下去就是跑android init进程了,写的比较的粗略,具体的细节还是需要自己去看代码体会。