之前这篇,从整体展示了 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 函数:

 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 中读取,模拟器默认是 goldfish18 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 }

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

on early-init    start ueventd# create mountpoints    mkdir /mnt 0775 root system# setup the global environment    export PATH /sbin:/vendor/bin:/system/sbin:/system/bin:/system/xbin# Create cgroup mount points for process groups    mkdir /dev/cpuctl    mount cgroup none /dev/cpuctl cpu    chown system system /dev/cpuctl    chown system system /dev/cpuctl/tasks    chmod 0777 /dev/cpuctl/tasks    write /dev/cpuctl/cpu.shares 1024service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server    class main    socket zygote stream 666    onrestart write /sys/android_power/request_state wake    onrestart write /sys/power/state on    onrestart restart media    onrestart restart netd

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

  • Action 定义方式:
on <trigger>                        #以 on 开头,后面是触发器名字,触发器有3种方式:
<command> #1.只是一个名字,如: on early-init; 
  <command>                #2.name=value 对,如:on property:vold.decrypt=trigger_reset_main;
<command> #3.系统自带的,如:device-added-<path>,device-removed-<path>,service-exited-<name>
<command> #在触发器下一行就是在触发器触发的时候需要执行的命令,如:start...,mkdir,...
  • Command 就是系统支持的一系列命令,如:export,hostname,mkdir,mount,等等,其中一部分是 linux 命令,还有一些是 android 添加的,如:class_start <serviceclass>: 启动服务,
    class_stop <serviceclass>:关闭服务,等等。
  • Service 定义方式:
service <name> <pathname> [ <argument> ]*   <option>   <option>   ...#如:启动 android 最重要的服务 zygote service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server    class main    socket zygote stream 666    onrestart write /sys/android_power/request_state wake    onrestart write /sys/power/state on    onrestart restart media    onrestart restart netd
  • Option 是针对 Service 的选项,如:
setenv <name> <value>                           在启动服务时设置环境变量user <username>                                 运行服务之前切换用户oneshot                                         如果服务已经存在,将不再启动class <classname>                               为服务设置名字,具有相同名字的服务将一起启动或者关闭
socket <name> <type> <perm> [ <user> [ <group> ] ]      创建以<name>命名的 socket,并将该 socket 的文件描述符返回给启动的服务
onrestart <command>                        在服务重新启动的时候执行<command>

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

  // 寻找 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(); ... }

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

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

class core:service ueventd /sbin/ueventdservice console /system/bin/shservice adbd /sbin/adbdservice servicemanager /system/bin/servicemanagerservice vold /system/bin/voldclass main:service netd /system/bin/netdservice debuggerd /system/bin/debuggerdservice ril-daemon /system/bin/rildservice surfaceflinger /system/bin/surfaceflingerservice zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-serverservice drm /system/bin/drmserverservice media /system/bin/mediaserverservice bootanim /system/bin/bootanimationservice dbus /system/bin/dbus-daemon --system --noforkservice bluetoothd /system/bin/bluetoothd -nservice installd /system/bin/installdservice flash_recovery /system/etc/install-recovery.shservice racoon /system/bin/racoonservice mtpd /system/bin/mtpdservice keystore /system/bin/keystore /data/misc/keystoreservice dumpstate /system/bin/dumpstate -s

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

#目录 权限 user group

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

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

int main(int argc, const char* const argv[]){    // These are global variables in ProcessState.cpp    mArgC = argc;    mArgV = argv;    mArgLen = 0;

//读取参数,传递的参数就是 init.rc 中启动时传入的: -Xzygote /system/bin --zygote --start-system-server
for (int i=0; i<argc; 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 < argc) { const char* arg = argv[i++]; if (!parentDir) { 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; }}

检测传入参数,将调用 :

 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:

void AndroidRuntime::start(const char* className, const char* options){    LOGD("\n>>>>>> AndroidRuntime START %s <<<<<<\n",            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");}

ZygoteInit 类 main 函数:

 public static void main(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(); throw ex; } }

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

更多相关文章

  1. 每周总结20130821——android控件的尺寸、http文件上传
  2. Android 配置及adb 命令
  3. Android调用系统自带的文件管理器进行文件选择并获得路径,android
  4. Android 文件的保存与读取之SDCard(SD卡)存储

随机推荐

  1. 使用Android(安卓)Studio的AVD进行测试
  2. Android adb不是内部或外部命令 问题解决
  3. Android Button Maker(在线生成android sh
  4. AndroidManifest.xml的Service元素 andro
  5. Android File文件操作
  6. android inputmanager中事件的传递流程
  7. android导航设计
  8. Android异步消息框架
  9. android中如何给button加圆角
  10. Android实现打电话功能