之前这篇,从整体展示了 android 的整个启动流程,为了搞清楚 android 启动到底在代码层面上是如何调用的,将从源代码角度去分析,另所有代码基于 android 4.0 source tree

all story begin with the init process startup故事从 init 进程启动开始

init 运行,代码:system/core/init ,入口:system/core/init/init.c  main 函数:

30810041_1.gif

1 int main(int argc, char **argv){2

3 ...4 // 初始化文件系统

5 mkdir("/dev", 0755);6 mkdir("/proc", 0755);7 mkdir("/sys", 0755);8

9 mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755");10 mkdir("/dev/pts", 0755);11 mkdir("/dev/socket", 0755);12 mount("devpts", "/dev/pts", "devpts", 0, NULL);13 mount("proc", "/proc", "proc", 0, NULL);14 mount("sysfs", "/sys", "sysfs", 0, NULL);15

16 ...17 // 解析 /init.rc 和 /init.$hardware.rc 脚本,其中 $hardware 参数从 /proc/cpuinfo 中读取,模拟器默认是 goldfish

18 INFO("reading config file\n");19 init_parse_config_file("/init.rc");20

21 /*pull the kernel commandline and ramdisk properties file in*/

22 import_kernel_cmdline(0, import_kernel_nv);23 /*don't expose the raw commandline to nonpriv processes*/

24 chmod("/proc/cmdline", 0440);25 get_hardware_name(hardware, &revision);26 snprintf(tmp, sizeof(tmp), "/init.%s.rc", hardware);27 init_parse_config_file(tmp);28

29 ...30 }

30810041_1.gif

解析 init.rc 文件,主要是由 /system/core/init/init_parser.c 来完成,截取 init.rc 的部分内容如下:(具体 init.rc 文件规范,可参考:/system/core/init/readme.txt)

30810041_1.gif

on early-init

start ueventd

# create mountpointsmkdir /mnt 0775root system

# setup the global environment

export PATH/sbin:/vendor/bin:/system/sbin:/system/bin:/system/xbin

# Create cgroupmount points for process groups

mkdir /dev/cpuctlmount cgroup none /dev/cpuctl cpuchown system system /dev/cpuctlchown system system /dev/cpuctl/taskschmod 0777 /dev/cpuctl/taskswrite /dev/cpuctl/cpu.shares 1024service zygote/system/bin/app_process -Xzygote /system/bin --zygote --start-system-server

class main

socket zygote stream666onrestartwrite /sys/android_power/request_state wake

onrestartwrite /sys/power/state on

onrestart restart media

onrestart restart netd

30810041_1.gif

init.rc 使用的是 android init language 规范,它支持4种语句,Actions,Commands,Services,Options:

Action 定义方式:

on #以 on 开头,后面是触发器名字,触发器有3种方式:

#1.只是一个名字,如: on early-init;                  #2.name=value 对,如:on property:vold.decrypt=trigger_reset_main;

#3.系统自带的,如:device-added-,device-removed-,service-exited-

#在触发器下一行就是在触发器触发的时候需要执行的命令,如:start...,mkdir,...

Command 就是系统支持的一系列命令,如:export,hostname,mkdir,mount,等等,其中一部分是 linux 命令,还有一些是 android 添加的,如:class_start : 启动服务,class_stop :关闭服务,等等。

Service 定义方式:

30810041_1.gif

service [ ]*

...

#如:启动 android 最重要的服务 zygote

service zygote/system/bin/app_process -Xzygote /system/bin --zygote --start-system-server

class main

socket zygote stream666onrestartwrite /sys/android_power/request_state wake

onrestartwrite /sys/power/state on

onrestart restart media

onrestart restart netd

30810041_1.gif

Option 是针对 Service 的选项,如:

setenv                   在启动服务时设置环境变量

user                   运行服务之前切换用户

oneshot                   如果服务已经存在,将不再启动

class                   为服务设置名字,具有相同名字的服务将一起启动或者关闭

socket [ [ ] ]      创建以命名的 socket,并将该 socket 的文件描述符返回给启动的服务

onrestart                         在服务重新启动的时候执行

在对 init.rc 和 init.$hardware.rc 2个文件按照 android init language 规范进行解析完成以后,会将所有将要执行的命令放到一个大的 action_list 当中,然后紧跟上面解析 init 文件下面:

30810041_1.gif

// 寻找 early-init 触发器,加到 action_queue 中

action_for_each_trigger("early-init", action_add_queue_tail);

// 添加系统的一些触发器

queue_builtin_action(wait_for_coldboot_done_action,"wait_for_coldboot_done");

queue_builtin_action(property_init_action,"property_init");

queue_builtin_action(keychord_init_action,"keychord_init");

queue_builtin_action(console_init_action,"console_init");

queue_builtin_action(set_init_properties_action,"set_init_properties");/*execute all the boot actions to get us started*/action_for_each_trigger("init", action_add_queue_tail);/*skip mounting filesystems in charger mode*/

if (strcmp(bootmode, "charger") != 0) {

action_for_each_trigger("early-fs", action_add_queue_tail);

action_for_each_trigger("fs", action_add_queue_tail);

action_for_each_trigger("post-fs", action_add_queue_tail);

action_for_each_trigger("post-fs-data", action_add_queue_tail);

}

queue_builtin_action(property_service_init_action,"property_service_init");

queue_builtin_action(signal_init_action,"signal_init");

queue_builtin_action(check_startup_action,"check_startup");if (!strcmp(bootmode, "charger")) {

action_for_each_trigger("charger", action_add_queue_tail);

}else{

action_for_each_trigger("early-boot", action_add_queue_tail);

action_for_each_trigger("boot", action_add_queue_tail);

}/*run all property triggers based on current state of the properties*/queue_builtin_action(queue_property_triggers_action,"queue_propety_triggers");

...

// 按顺序执行 action_queue 中的命令

for(;;) {int nr, i, timeout = -1;

execute_one_command();

restart_processes();

...}

30810041_1.gif

从 action_list 中找到制定触发器,将触发器需要执行的命令添加到 action_queue 中,最后按顺序执行 action_queue 中的命令来完成初始化,初始化除了设置一些环境变量和创建文件夹以外,

更多的是关心 Service 的启动,init 文件里面的服务有2种,1种是 class core,还有1种是 class main,对 init.rc 的 service 按照 class 分类如下:

30810041_1.gif

class core:

service ueventd/sbin/ueventd

service console/system/bin/shservice adbd/sbin/adbd

service servicemanager/system/bin/servicemanager

service vold/system/bin/vold

class main:

service netd/system/bin/netd

service debuggerd/system/bin/debuggerd

service ril-daemon /system/bin/rild

service surfaceflinger/system/bin/surfaceflinger

service zygote/system/bin/app_process -Xzygote /system/bin --zygote --start-system-server

service drm/system/bin/drmserver

service media/system/bin/mediaserver

service bootanim/system/bin/bootanimation

service dbus/system/bin/dbus-daemon --system --nofork

service bluetoothd/system/bin/bluetoothd -n

service installd/system/bin/installd

service flash_recovery/system/etc/install-recovery.shservice racoon/system/bin/racoon

service mtpd/system/bin/mtpd

service keystore/system/bin/keystore /data/misc/keystore

service dumpstate/system/bin/dumpstate -s

30810041_1.gif

service ueventd:会读取 /ueventd.rc 和 /ueventd.$hadrware.rc 文件,解析跟 init.rc 解析类似,主要是对文件系统的权限和用户进行设置:(代码:system/core/init/ueventd.c)

#目录 权限 user group

/dev/null 0666root root/dev/zero 0666 root root

在 class core 服务启动以后, class main 开始启动,service zygote 是标志进入 android 最重要的一个服务,服务名字 zygote,实际上启动的是 app_process,(代码:frameworks/base/cmds/app_process/app_main.cpp)

30810041_1.gif

int main(int argc, const char* constargv[])

{//These are global variables in ProcessState.cpp

mArgC =argc;

mArgV=argv;

mArgLen= 0;

//读取参数,传递的参数就是 init.rc 中启动时传入的: -Xzygote /system/bin --zygote --start-system-serverfor (int i=0; i

mArgLen+= strlen(argv[i]) + 1;

}

mArgLen--;

AppRuntime runtime;const char* argv0 = argv[0]; //-Xzygote//Process command line arguments//ignore argv[0]

argc--; //之前是 4, 现在是 3

argv++; //argv 指向 argv[1]//Everything up to '--' or first non '-' arg goes to the vm

// i = 0,代码:frameworks/base/core/jni/AndroidRuntime.cpp

int i =runtime.addVmArguments(argc, argv);//Parse runtime arguments. Stop at first unrecognized option.

bool zygote = false;bool startSystemServer = false;bool application = false;const char* parentDir =NULL;const char* niceName =NULL;const char* className =NULL;while (i

parentDir=arg;               //parentDir = /system/bin

}else if (strcmp(arg, "--zygote") == 0) { //当 i = 2,arg = argv[1] 时,即:--zygote

zygote= true;

niceName= "zygote";

}else if (strcmp(arg, "--start-system-server") == 0) {

startSystemServer= true;

}else if (strcmp(arg, "--application") == 0) {

application= true;

}else if (strncmp(arg, "--nice-name=", 12) == 0) {

niceName= arg + 12;

}else{

className=arg;break;

}

}if (niceName && *niceName) {

setArgv0(argv0, niceName);

set_process_name(niceName);

}

runtime.mParentDir=parentDir;if(zygote) {

// zygote = true,启动 com.android.internal.os.ZygoteInit,参数:startSystemServer

runtime.start("com.android.internal.os.ZygoteInit",startSystemServer? "start-system-server" : "");

}else if(className) {//Remainder of args get passed to startup class main()

runtime.mClassName =className;

runtime.mArgC= argc -i;

runtime.mArgV= argv +i;

runtime.start("com.android.internal.os.RuntimeInit",

application? "application" : "tool");

}else{

fprintf(stderr,"Error: no class name or --zygote supplied.\n");

app_usage();

LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");return 10;

}

}

30810041_1.gif

检测传入参数,将调用 :

runtime.start("com.android.internal.os.ZygoteInit",startSystemServer ? "start-system-server" : "");

runtime 的代码:frameworks/base/core/jni/AndroidRuntime.cpp,start 函数会启动虚拟机, 执行 com.android.internal.os.ZygoteInit 该类的 main 函数,并传入参数: start-system-server:

30810041_1.gif

void AndroidRuntime::start(const char* className, const char*options)

{

LOGD("\n>>>>>> AndroidRuntime START %s <<<<<

className!= NULL ? className : "(unknown)");

...

/*start the virtual machine*/

//设置 dalvik 虚拟机参数,创建并启动虚拟机JNIEnv*env;if (startVm(&mJavaVM, &env) != 0) {return;

}

onVmCreated(env);/** Register android functions.*/

if (startReg(env) < 0) {

LOGE("Unable to register all android natives\n");return;

}.../** Start VM. This thread becomes the main thread of the VM, and will

* not return until the VM exits.*/ //将类名 com.xxx.xxx 转换成 com/xxx/xxx

char* slashClassName =toSlashClassName(className);

jclass startClass= env->FindClass(slashClassName);if (startClass ==NULL) {

LOGE("JavaVM unable to locate class '%s'\n", slashClassName);/*keep going*/}else{

// jni 调用 java 方法,获取对应类名的 class,然后调用静态 main 方法

jmethodID startMeth= env->GetStaticMethodID(startClass, "main","([Ljava/lang/String;)V");if (startMeth ==NULL) {

LOGE("JavaVM unable to find main() in '%s'\n", className);/*keep going*/}else{

env->CallStaticVoidMethod(startClass, startMeth, strArray);}

}

free(slashClassName);

LOGD("Shutting down VM\n");if (mJavaVM->DetachCurrentThread() !=JNI_OK)

LOGW("Warning: unable to detach main thread\n");if (mJavaVM->DestroyJavaVM() != 0)

LOGW("Warning: VM did not shut down cleanly\n");

}

30810041_1.gif

ZygoteInit 类 main 函数:

30810041_1.gif

public static voidmain(String argv[]) {try{//Start profiling the zygote initialization.

SamplingProfilerIntegration.start();

//注册 socket server

registerZygoteSocket();

EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,

SystemClock.uptimeMillis());

//预加载资源,有 preloadClasses() 和 preloadResources(),加载的开始和结束会被记录在 /system/etc/event-log-tags 文件中

preload();

EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,

SystemClock.uptimeMillis());//Finish profiling the zygote initialization.

SamplingProfilerIntegration.writeZygoteSnapshot();//Do an initial gc to clean up after startup

gc();//If requested, start system server directly from Zygote

if (argv.length != 2) {throw new RuntimeException(argv[0] +USAGE_STRING);

}if (argv[1].equals("start-system-server")) {

//在调用 Zygote 的 main 函数时,已经传入 start-system-server,调用 startSystemServer()

startSystemServer();

}else if (!argv[1].equals("")) {throw new RuntimeException(argv[0] +USAGE_STRING);

}

Log.i(TAG,"Accepting command socket connections");if(ZYGOTE_FORK_MODE) {

runForkMode();

}else{

//上面通过 registerZygoteSocket() 函数调用注册的 server scocket,会启动,开始监听 Zygote 连接

runSelectLoopMode();

}

closeServerSocket();

}catch(MethodAndArgsCaller caller) {

caller.run();

}catch(RuntimeException ex) {

Log.e(TAG,"Zygote died with exception", ex);

closeServerSocket();throwex;

}

}

30810041_1.gif

那 startSystemServer 到底又做了什么东东呢,以及最后系统如何发出 ACTION_BOOT_COMPLETED 广播的呢,且听下回分解。 -):

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐