Android起动流程分析(二) init进程的启动

Android启动流程分析(二) init进程的启动

#############################################

本文为极度寒冰原创,转载请注明出处
#############################################
分析init进程,首先要分析init进程是如何启动的, init的源码位于(system/core/init),我们先来看看init进程的android.mk
下面是从system/core/init模块拿出来的一段code:
LOCAL_MODULE:= init
LOCAL_FORCE_STATIC_EXECUTABLE := true
LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT)
LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_UNSTRIPPED)
LOCAL_STATIC_LIBRARIES := \
        libfs_mgr \
        liblogwrap \
        libcutils \
        liblog \
        libc \
        libselinux \
        libmincrypt \
        libext4_utils_static
LOCAL_ADDITIONAL_DEPENDENCIES += $(LOCAL_PATH)/Android.mk
include $(BUILD_EXECUTABLE)
我们发现,init的代码其实是被编译成了一个可执行的程序:
include $(BUILD_EXECUTABLE)
程序的名字是叫:
LOCAL_MODULE:= init
那么init的可执行应用程序是怎么被启动的呢?
这下就是kernel与android ap端的联系了。

我们看一下kernel的code:
在kernel的code:init/main.c的main函数中,我们看到了如下的代码:
878	if (!ramdisk_execute_command)
879		ramdisk_execute_command = "/init";
880
881	if (sys_access((const char __user *) ramdisk_execute_command, 0) != 0) {
882		ramdisk_execute_command = NULL;
883		prepare_namespace();
884	}
我们发现,ramdisk_execute_command被初始化为了init
sys_access((const char __user *) ramdisk_execute_command, 0) 
判断系统中是否存在/init的命令,如果不存在的话,会将ramdisk_execute_command置为NUll
并且会去继续寻找,检查是否有没有挂载的文件系统,initrd就是在这个函数中被挂载的。

而对于我们android来讲,一般正常的情况下,我们会去执行
init_post();
而这个函数的实现如下:
795/* This is a non __init function. Force it to be noinline otherwise gcc
796 * makes it inline to init() and it becomes part of init.text section
797 */
798static noinline int init_post(void)
799{
800	/* need to finish all async __init code before freeing the memory */
801	async_synchronize_full();
802	free_initmem();
803	mark_rodata_ro();
804	system_state = SYSTEM_RUNNING;
805	numa_default_policy();
806
807
808	current->signal->flags |= SIGNAL_UNKILLABLE;
809
810	if (ramdisk_execute_command) {
811		run_init_process(ramdisk_execute_command);
812		printk(KERN_WARNING "Failed to execute %s\n",
813				ramdisk_execute_command);
814	}
815
816	/*
817	 * We try each of these until one succeeds.
818	 *
819	 * The Bourne shell can be used instead of init if we are
820	 * trying to recover a really broken machine.
821	 */
822	if (execute_command) {
823		run_init_process(execute_command);
824		printk(KERN_WARNING "Failed to execute %s.  Attempting "
825					"defaults...\n", execute_command);
826	}
827	run_init_process("/sbin/init");
828	run_init_process("/etc/init");
829	run_init_process("/bin/init");
830	run_init_process("/bin/sh");
831
832	panic("No init found.  Try passing init= option to kernel. "
833	      "See Linux Documentation/init.txt for guidance.");
834}
可以看到,当ramdisk_execute_command不为NULL的时候,就会去run run_init_process.
<pre name="code" class="cpp" style="font-size: 13.63636302948px; line-height: 25.9943180084229px;">789static void run_init_process(const char *init_filename)
790{
791	argv_init[0] = init_filename;
792	kernel_execve(init_filename, argv_init, envp_init);
793}
794

看到这里,我们就看明白了。这里就会去执行我们ap端编译出来的的init的命令,也就是会进入到/system/core/init的目录下

从此完成了kernel到init的链接