Android之kernel启动init流程


一、kernel侧
1.kernel/arch/arm64/kernel/head.S
bl	kasan_early_init
add	sp, sp, #16
mov	x29, #0
mov	x30, #0
b	start_kernel

2.kernel/init/main.c
<1>.asmlinkage __visible void __init start_kernel(void){
 
 /* Do the rest non-__init'ed, we're now alive */
 rest_init();
}

<2>.static noinline void __ref rest_init(void){
  pid = kernel_thread(kernel_init, NULL, CLONE_FS);
}

<3>.static int __ref kernel_init(void *unused){
  pr_emerg("run init\n");
	if (ramdisk_execute_command) {
		ret = run_init_process(ramdisk_execute_command);
		if (!ret)
			return 0;
		pr_err("Failed to execute %s (error %d)\n",
		       ramdisk_execute_command, ret);
	}

	/*
	 * We try each of these until one succeeds.
	 *
	 * The Bourne shell can be used instead of init if we are
	 * trying to recover a really broken machine.
	 */
	if (execute_command) {
		ret = run_init_process(execute_command);
		if (!ret)
			return 0;
		panic("Requested init %s failed (error %d).",
		      execute_command, ret);
	}
	if (!try_to_run_init_process("/sbin/init") ||
	    !try_to_run_init_process("/etc/init") ||
	    !try_to_run_init_process("/bin/init") ||
	    !try_to_run_init_process("/bin/sh"))
		return 0;
}
注意:
 run_init_process运行init bin,从kernel_init函数中可知,系统会依次去找根目录下的init,execute_command,/sbin/init,/etc/init,/bin/init,/bin/sh这六个可执行文件,只要找到其中一个,其他就不执行。
 
 
 二、android侧
 1.system/core/init/main.cpp
 int main(int argc, char** argv) {
#if __has_feature(address_sanitizer)
    __asan_set_error_report_callback(AsanReportCallback);
#endif

    if (!strcmp(basename(argv[0]), "ueventd")) {
        return ueventd_main(argc, argv);
    }

    if (argc > 1) {
        if (!strcmp(argv[1], "subcontext")) {
            android::base::InitLogging(argv, &android::base::KernelLogger);
            const BuiltinFunctionMap function_map;

            return SubcontextMain(argc, argv, &function_map);
        }

        if (!strcmp(argv[1], "selinux_setup")) {
            android::mboot::mdb("SELinux Setup ...");
            return SetupSelinux(argv);
        }

        if (!strcmp(argv[1], "second_stage")) {
            return SecondStageMain(argc, argv);
        }
    }

    return FirstStageMain(argc, argv);
}
 
注意:
第一步:挂载文件系统
Android根文件系统的映像中不存在“/dev”目录,该目录是init进程启动后动态创建的。
因此,建立Android中设备节点文件的重任,也落在了init进程身上。为此,init进程创建子进程ueventd,并将创建设备节点文件的工作托付给ueventd。ueventd通过两种方式创建设备节点文件。
第一种方式对应“冷插拔”(Cold Plug),即以预先定义的设备信息为基础,当ueventd启动后,统一创建设备节点文件。这一类设备节点文件也被称为静态节点文件。
第二种方式对应“热插拔”(Hot Plug),即在系统运行中,当有设备插入USB端口时,ueventd就会接收到这一事件,为插入的设备动态创建设备节点文件。这一类设备节点文件也被称为动态节点文件。

猜你喜欢

转载自blog.csdn.net/u010164190/article/details/125300832