Init进程是Linux系统中用户空间的第一个进程,其进程号为1。

Android本质上就是一个基于Linux内核的操作系统。与 Linux的最大的区别是, Android 在应用层专门为移动设备添加了一些特有的支持。例如进程间通信机制中增加的Binder通信等。

Android系统启动流程的前几步:
1.启动电源以及系统启动
当电源按下时引导芯片代码开始从预定义的地方(固化在ROM)开始执行。加载引导程序Bootloader到RAM,然后执行。 
2.引导程序Bootloader 
引导程序是在Android操作系统开始运行前的一个小程序,它的主要作用是把系统OS拉起来并运行。 

3.linux内核启动 
内核启动时,设置缓存、被保护存储器、计划列表,加载驱动。当内核完成系统设置,它首先在系统文件中寻找”init”文件,然后启动root进程或者系统的第一个进程加载完Linux基本内核后开始初始化进程Init的。

4.init进程启动


本文主要分析init启动到zygote,systemserver启动的过程


1.init启动过程

Init进程主要做的事情为:
        初始化属性;
        处理配置文件的命令(主要是init.rc文件),包括处理各种Action;
        无限循环执行command(启动其他进程);

Init源码的主要目录:
        /system/core/init/
    主要jni代码:
        /frameworks/base/core/jni/
    涉及的其他目录:
        /bionic/libc/bionic/libc_init_common.cpp
        /bionic/libc/bionic/libc_init_common.h
        /bionic/libc/bionic/libc_init_dynamic.cpp

        /bionic/libc/bionic/libc_init_static.cpp
    属性核心文件:
        system/core/libcutils/properties.cpp
主要分为两部分:
        1.初始化:初始化主要包括建立/dev、/proc等目录,初始化属性,执行init.rc等初始化文件中的Action等。
        2.使用while的无限循环来建立子进程。

Linux中除过init外的其他进程都是init负责创建的,都是在这个无限while循环中完成的;而且init也会常驻内容

 代码路径:/system/core/init/init.cpp

    (http://androidxref.com/8.0.0_r4/xref/system/core/init/init.cpp)

  在main函数一开始主要进行一开始的准备工作,例如ueventd和看门狗判断,和信号系统安装,系统环境变量的添加工作

948int main(int argc, char** argv) {949    if (!strcmp(basename(argv[0]), "ueventd")) {//判断是否为ueventd950        return ueventd_main(argc, argv);951    }952     //判断是否为看门狗953    if (!strcmp(basename(argv[0]), "watchdogd")) {954        return watchdogd_main(argc, argv);955    }956957    if (REBOOT_BOOTLOADER_ON_PANIC) {958        install_reboot_signal_handlers();959    }960961    add_environment("PATH", _PATH_DEFPATH);//添加环境变量962
main函数中此段代码主要做的工作就是:创建文件系统目录并挂载相关的文件系统
963    bool is_first_stage = (getenv("INIT_SECOND_STAGE") == nullptr);//创建文件并挂载964965    if (is_first_stage) {966        boot_clock::time_point start_time = boot_clock::now();967968        // Clear the umask.969        umask(0); //清除屏蔽字(file mode creation mask),保证新建的目录的访问权限不受屏蔽字影响970971        // Get the basic filesystem setup we need put together in the initramdisk972        // on / and then we'll let the rc file figure out the rest.973        mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755"); //挂载tmpfs文件系统 974        mkdir("/dev/pts", 0755);975        mkdir("/dev/socket", 0755);976        mount("devpts", "/dev/pts", "devpts", 0, NULL);// 挂载devpts文件系统 977        #define MAKE_STR(x) __STRING(x)978        mount("proc", "/proc", "proc", 0, "hidepid=2,gid=" MAKE_STR(AID_READPROC));// 挂载proc文件系统 979        // Don't expose the raw commandline to unprivileged processes.980        chmod("/proc/cmdline", 0440);981        gid_t groups[] = { AID_READPROC };982        setgroups(arraysize(groups), groups);983        mount("sysfs", "/sys", "sysfs", 0, NULL);// 挂载sysfs文件系统984        mount("selinuxfs", "/sys/fs/selinux", "selinuxfs", 0, NULL);// 挂载selinuxfs文件系统985        mknod("/dev/kmsg", S_IFCHR | 0600, makedev(1, 11));986        mknod("/dev/random", S_IFCHR | 0666, makedev(1, 8));987        mknod("/dev/urandom", S_IFCHR | 0666, makedev(1, 9));988
   

   
   
开始解析之前的各类初始化准备工作
989        // Now that tmpfs is mounted on /dev and we have /dev/kmsg, we can actually990        // talk to the outside world...991        InitKernelLogging(argv);//内核log初始化992993        LOG(INFO) << "init first stage started!";994995        if (!DoFirstStageMount()) {996            LOG(ERROR) << "Failed to mount required partitions early ...";997            panic();998        }9991000        SetInitAvbVersionInRecovery();//判断是否为recovery模式10011002        // Set up SELinux, loading the SELinux policy.1003        selinux_initialize(true);//初始化selinux10041005        // We're in the kernel domain, so re-exec init to transition to the init domain now1006        // that the SELinux policy has been loaded.1007        if (restorecon("/init") == -1) {1008            PLOG(ERROR) << "restorecon failed";1009            security_failure();1010        }10111012        setenv("INIT_SECOND_STAGE", "true", 1);10131014        static constexpr uint32_t kNanosecondsPerMillisecond = 1e6;1015        uint64_t start_ms = start_time.time_since_epoch().count() / kNanosecondsPerMillisecond;1016        setenv("INIT_STARTED_AT", StringPrintf("%" PRIu64, start_ms).c_str(), 1);10171018        char* path = argv[0];1019        char* args[] = { path, nullptr };1020        execv(path, args);10211022        // execv() only returns if an error happened, in which case we1023        // panic and never fall through this conditional.1024        PLOG(ERROR) << "execv(\"" << path << "\") failed";1025        security_failure();1026    }10271028    // At this point we're in the second stage of init.1029    InitKernelLogging(argv);1030    LOG(INFO) << "init second stage started!";10311032    // Set up a session keyring that all processes will have access to. It1033    // will hold things like FBE encryption keys. No process should override1034    // its session keyring.1035    keyctl(KEYCTL_GET_KEYRING_ID, KEY_SPEC_SESSION_KEYRING, 1);10361037    // Indicate that booting is in progress to background fw loaders, etc.1038    close(open("/dev/.booting", O_WRONLY | O_CREAT | O_CLOEXEC, 0000));// 检测/dev/.booting文件是否可读写、创建等
10391040    property_init();// 初始化属性域 --> 定义于system/core/init/property_service.cpp10411042    // If arguments are passed both on the command line and in DT,1043    // properties set in DT always have priority over the command-line ones.1044    process_kernel_dt();//dt中的属性设置1045    process_kernel_cmdline();//处理内核命令行,dt中的属性总是优先于内核命令行10461047    // Propagate the kernel variables to internal variables1048    // used by init as well as the current required properties.1049    export_kernel_boot_props();//将内核变量传播给init使用的内部变量以及当前所需的属性10501051    // Make the time that init started available for bootstat to log.1052    property_set("ro.boottime.init", getenv("INIT_STARTED_AT"));//设置boot启动时间在log中1053    property_set("ro.boottime.init.selinux", getenv("INIT_SELINUX_TOOK"));//设置selinux启动时间在log中1054
1055    // Set libavb version for Framework-only OTA match in Treble build.1056    const char* avb_version = getenv("INIT_AVB_VERSION");1057    if (avb_version) property_set("ro.boot.avb_version", avb_version);//在Treble版本中设置libavb版本以进行仅限框架的OTA匹配10581059    // Clean up our environment.1060    unsetenv("INIT_SECOND_STAGE");1061    unsetenv("INIT_STARTED_AT");1062    unsetenv("INIT_SELINUX_TOOK");1063    unsetenv("INIT_AVB_VERSION");10641065    // Now set up SELinux for second stage.1066    selinux_initialize(false);//加载SELinux策略, 后面有一些初始化文件上下文的操作等1067    selinux_restore_context();10681069    epoll_fd = epoll_create1(EPOLL_CLOEXEC);1070    if (epoll_fd == -1) {1071        PLOG(ERROR) << "epoll_create1 failed";1072        exit(1);1073    }10741075    signal_handler_init();///初始化子进程退出的信号处理过程10761077    property_load_boot_defaults();//加载/default.prop文件1078    export_oem_lock_status();1079    start_property_service();//启动属性服务器(通过socket通信)1080    set_usb_controller();10811082    const BuiltinFunctionMap function_map;1083    Action::set_function_map(&function_map);1084
   

   
   
   
   
正式开启解析init.rc工作1085    Parser& parser = Parser::GetInstance();1086    parser.AddSectionParser("service",std::make_unique());//设置对应的解析函数 “service”块以关键字“service”开始,表示启动某个进程的方式和参数1087    parser.AddSectionParser("on", std::make_unique());//“action”块以关键字“on”开始,表示一堆命令的集合1088    parser.AddSectionParser("import", std::make_unique()); //“import”是用来引入一个init配置文件,来扩展当前配置的1089    std::string bootscript = GetProperty("ro.boot.init_rc", "");1090    if (bootscript.empty()) {1091        parser.ParseConfig("/init.rc");1092        parser.set_is_system_etc_init_loaded(1093                parser.ParseConfig("/system/etc/init"));1094        parser.set_is_vendor_etc_init_loaded(1095                parser.ParseConfig("/vendor/etc/init"));1096        parser.set_is_odm_etc_init_loaded(parser.ParseConfig("/odm/etc/init"));1097    } else {1098        parser.ParseConfig(bootscript);1099        parser.set_is_system_etc_init_loaded(true);1100        parser.set_is_vendor_etc_init_loaded(true);1101        parser.set_is_odm_etc_init_loaded(true);1102    }11031104    // Turning this on and letting the INFO logging be discarded adds 0.2s to1105    // Nexus 9 boot time, so it's disabled by default.1106    if (false) parser.DumpState();11071108    ActionManager& am = ActionManager::GetInstance();11091110    am.QueueEventTrigger("early-init");11111112    // Queue an action that waits for coldboot done so we know ueventd has set up all of /dev...1113    am.QueueBuiltinAction(wait_for_coldboot_done_action, "wait_for_coldboot_done");1114    // ... so that we can start queuing up actions that require stuff from /dev.1115    am.QueueBuiltinAction(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");1116    am.QueueBuiltinAction(set_mmap_rnd_bits_action, "set_mmap_rnd_bits");1117    am.QueueBuiltinAction(set_kptr_restrict_action, "set_kptr_restrict");1118    am.QueueBuiltinAction(keychord_init_action, "keychord_init");1119    am.QueueBuiltinAction(console_init_action, "console_init");11201121    // Trigger all the boot actions to get us started.1122    am.QueueEventTrigger("init");11231124    // Repeat mix_hwrng_into_linux_rng in case /dev/hw_random or /dev/random1125    // wasn't ready immediately after wait_for_coldboot_done1126    am.QueueBuiltinAction(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");11271128    // Don't mount filesystems or start core system services in charger mode.1129    std::string bootmode = GetProperty("ro.bootmode", "");1130    if (bootmode == "charger") {1131        am.QueueEventTrigger("charger");1132    } else {1133        am.QueueEventTrigger("late-init");1134    }11351136    // Run all property triggers based on current state of the properties.1137    am.QueueBuiltinAction(queue_property_triggers_action, "queue_property_triggers");
   

init.rc的过程就是识别一个个section的过程,将各个section的信息保存下来,然后在init.c的main()中去执行一个个命令。 android采用双向链表(关于双向链表详解见本文第三部分)来存储section的信息,解析完成之后,会得到三个双向链表action_list、service_list、import_list来分别存储三种section的信息上

init.rc解析完成之后,所有的启动项目都被放入到action_add_queue_tail中,接着调用action_for_each_trigger("early-init", action_add_queue_tail),触发early-init触发器来出发这些相关services和actions的运行。

使用while的无限循环来建立子进程
   
          
11381139    while (true) {1140        // By default, sleep until something happens.1141        int epoll_timeout_ms = -1;//以下决定epoll_timeout_ms的时间,将影响while循环的间隔11421143        if (!(waiting_for_prop || ServiceManager::GetInstance().IsWaitingForExec())) {1144            am.ExecuteOneCommand();1145        }1146        if (!(waiting_for_prop || ServiceManager::GetInstance().IsWaitingForExec())) {1147            restart_processes();11481149            // If there's a process that needs restarting, wake up in time for that.1150            if (process_needs_restart_at != 0) {//有进程需要重启时,等待该进程重启1151                epoll_timeout_ms = (process_needs_restart_at - time(nullptr)) * 1000;1152                if (epoll_timeout_ms < 0) epoll_timeout_ms = 0;1153            }11541155            // If there's more work to do, wake up again immediately.1156            if (am.HasMoreCommands()) epoll_timeout_ms = 0;1157        }11581159        epoll_event ev;1160        int nr = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd, &ev, 1, epoll_timeout_ms));1161        if (nr == -1) {1162            PLOG(ERROR) << "epoll_wait failed";1163        } else if (nr == 1) {1164            ((void (*)()) ev.data.ptr)();1165        }1166    }11671168    return 0;1169}

在 init 进程中 ,配置文件是指文件 init.rc,其路径是:
/system/core/rootdir/init .rc
文件 init.rc 是一个可配置的初始化文件 ,在里面定制了厂商可以配置的额外的初始化配置信息,具体格式为:
init.%PRODUCT%.rc
文件init.rc是在文件“/system/core/init/init.cpp”中读取的,它基于“行”,包含一些用空格隔开的关键字(它属于特殊字符)。如果在关键字中含有空格,则使用“/“表示转义,使用“”防止关键字被断开,如果“/”在末尾则表示换行,以“#”开头的表示注释。文件init.rc 包含 4 种状态类别 ,分别是 Actions 、Commands 、Services 和 Options ,当声明一个 Service  或者 Action  的时候,它将隐式声明一个 section,它之后跟随的Command或者Option都将属于这个 section。另外,Action    和 Service  不能重名,否则忽略为eπor
2.zygote启动过程
在init.rc中,early-init相关启动的services和actions。基本上是恢复某些文件或文件夹的安全上下文,然后调用init_zygote32_64.rc文件中的命令启动zygote

1service zygote /system/bin/app_process32 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote2    class main3    priority -204    user root5    group root readproc6    socket zygote stream 660 root system7    onrestart write /sys/android_power/request_state wake8    onrestart write /sys/power/state on9    onrestart restart audioserver10    onrestart restart cameraserver11    onrestart restart media12    onrestart restart netd13    onrestart restart wificond14    writepid /dev/cpuset/foreground/tasks1516service zygote_secondary /system/bin/app_process64 -Xzygote /system/bin --zygote --socket-name=zygote_secondary17    class main18    priority -2019    user root20    group root readproc21    socket zygote_secondary stream 660 root system22    onrestart restart zygote23    writepid /dev/cpuset/foreground/tasks

通过/system/bin/app_process32程序启动zygote进程,参数为--zygote和--start-system-server,这两个参数在后面我们会用到的。下面我们来看一下Zygote的main函数

 

zygote启动过程大体上分为七部分:

1.app_main.main

代码路径:/frameworks/base/cmds/app_process/app_main.cpp

    (http://androidxref.com/8.0.0_r4/xref//frameworks/base/cmds/app_process/app_main.cpp)

在Zygote进程中加载的应用程序文件为system/bin/app_process。 因此,接下来就从这个应用程序文件的入口函数main开始分析Zygote进程的启动过程

187int main(int argc, char* const argv[])188{189    if (!LOG_NDEBUG) {190      String8 argv_String;191      for (int i = 0; i < argc; ++i) {192        argv_String.append("\"");193        argv_String.append(argv[i]);194        argv_String.append("\" ");195      }196      ALOGV("app_process main with argv: %s", argv_String.string());197    }198199    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));//创建了一个AppRuntime对象runtime200    // Process command line arguments201    // ignore argv[0]202    argc--;203    argv++;204205    // Everything up to '--' or first non '-' arg goes to the vm.206    //207    // The first argument after the VM args is the "parent dir", which208    // is currently unused.209    //210    // After the parent dir, we expect one or more the following internal211    // arguments :212    //213    // --zygote : Start in zygote mode214    // --start-system-server : Start the system server.215    // --application : Start in application (stand alone, non zygote) mode.216    // --nice-name : The nice name for this process.217    //218    // For non zygote starts, these arguments will be followed by219    // the main class name. All remaining arguments are passed to220    // the main method of this class.221    //222    // For zygote starts, all remaining arguments are passed to the zygote.223    // main function.224    //225    // Note that we must copy argument string values since we will rewrite the226    // entire argument block when we apply the nice name to argv0.227    //228    // As an exception to the above rule, anything in "spaced commands"229    // goes to the vm even though it has a space in it.230    const char* spaced_commands[] = { "-cp", "-classpath" };231    // Allow "spaced commands" to be succeeded by exactly 1 argument (regardless of -s).232    bool known_command = false;233234    int i;235    for (i = 0; i < argc; i++) {236        if (known_command == true) {237          runtime.addOption(strdup(argv[i]));238          ALOGV("app_process main add known option '%s'", argv[i]);239          known_command = false;240          continue;241        }242243        for (int j = 0;244             j < static_cast(sizeof(spaced_commands) / sizeof(spaced_commands[0]));245             ++j) {246          if (strcmp(argv[i], spaced_commands[j]) == 0) {247            known_command = true;248            ALOGV("app_process main found known command '%s'", argv[i]);249          }250        }251252        if (argv[i][0] != '-') {253            break;254        }255        if (argv[i][1] == '-' && argv[i][2] == 0) {256            ++i; // Skip --.257            break;258        }259260        runtime.addOption(strdup(argv[i]));261        ALOGV("app_process main add option '%s'", argv[i]);262    }263264    // Parse runtime arguments.  Stop at first unrecognized option.265    bool zygote = false;266    bool startSystemServer = false;267    bool application = false;268    String8 niceName;269    String8 className;270271    ++i;  // Skip unused "parent dir" argument.272    while (i < argc) {273        const char* arg = argv[i++];274        if (strcmp(arg, "--zygote") == 0) {//检查应用程序 app_process 的启动参数arg是否包含了一个 “一zygote ” 选项。275            zygote = true;                 //如果包含了 ,那么就说明这时候应用程序app_process是在Zygote进程中启动的276            niceName = ZYGOTE_NICE_NAME;277        } else if (strcmp(arg, "--start-system-server") == 0) {278            startSystemServer = true;279        } else if (strcmp(arg, "--application") == 0) {280            application = true;281        } else if (strncmp(arg, "--nice-name=", 12) == 0) {282            niceName.setTo(arg + 12);283        } else if (strncmp(arg, "--", 2) != 0) {284            className.setTo(arg);285            break;286        } else {287            --i;288            break;289        }290    }291292    Vector args;293    if (!className.isEmpty()) {294        // We're not in zygote mode, the only argument we need to pass295        // to RuntimeInit is the application argument.296        //297        // The Remainder of args get passed to startup class main(). Make298        // copies of them before we overwrite them with the process name.299        args.add(application ? String8("application") : String8("tool"));300        runtime.setClassNameAndArgs(className, argc - i, argv + i);301302        if (!LOG_NDEBUG) {303          String8 restOfArgs;304          char* const* argv_new = argv + i;305          int argc_new = argc - i;306          for (int k = 0; k < argc_new; ++k) {307            restOfArgs.append("\"");308            restOfArgs.append(argv_new[k]);309            restOfArgs.append("\" ");310          }311          ALOGV("Class name = %s, args = %s", className.string(), restOfArgs.string());312        }313    } else {314        // We're in zygote mode.315        maybeCreateDalvikCache();316        317        if (startSystemServer) {318            args.add(String8("start-system-server"));319        }320321        char prop[PROP_VALUE_MAX];322        if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) {323            LOG_ALWAYS_FATAL("app_process: Unable to determine ABI list from property %s.",324                ABI_LIST_PROPERTY);325            return 11;326        }327328        String8 abiFlag("--abi-list=");329        abiFlag.append(prop);330        args.add(abiFlag);331332        // In zygote mode, pass all remaining arguments to the zygote333        // main() method.334        for (; i < argc; ++i) {335            args.add(String8(argv[i]));336        }337    }338339    if (!niceName.isEmpty()) {340        runtime.setArgv0(niceName.string(), true /* setProcName */);341    }342343    if (zygote) {//AppRuntime类的成员函数start是从其父类AndroidRuntime继承下来的,接下来分析AndroidRuntime类的成员函数start的实现344        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);345    } else if (className) {346        runtime.start("com.android.internal.os.RuntimeInit", args, zygote);347    } else {348        fprintf(stderr, "Error: no class name or --zygote supplied.\n");349        app_usage();350        LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");351    }352}
   

2.AndroidRuntime.start

代码路径:/frameworks/base/core/jni/AndroidRuntime.cpp

    (http://androidxref.com/8.0.0_r4/xref/frameworks/base/core/jni/AndroidRuntime.cpp)

986/*987 * Start the Android runtime.  This involves starting the virtual machine988 * and calling the "static void main(String[] args)" method in the class989 * named by "className".990 *991 * Passes the main function two arguments, the class name and the specified992 * options string.993 */994void AndroidRuntime::start(const char* className, const Vector& options, bool zygote)995{996    ALOGD(">>>>>> START %s uid %d <<<<<<\n",997            className != NULL ? className : "(unknown)", getuid());998999    static const String8 startSystemServer("start-system-server");10001001    /*1002     * 'startSystemServer == true' means runtime is obsolete and not run from1003     * init.rc anymore, so we print out the boot start event here.1004     */1005    for (size_t i = 0; i < options.size(); ++i) {1006        if (options[i] == startSystemServer) {1007           /* track our progress through the boot sequence */1008           const int LOG_BOOT_PROGRESS_START = 3000;1009           LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START,  ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));1010        }1011    }10121013    const char* rootDir = getenv("ANDROID_ROOT");1014    if (rootDir == NULL) {1015        rootDir = "/system";1016        if (!hasDir("/system")) {1017            LOG_FATAL("No root directory specified, and /android does not exist.");1018            return;1019        }1020        setenv("ANDROID_ROOT", rootDir, 1);1021    }10221023    //const char* kernelHack = getenv("LD_ASSUME_KERNEL");1024    //ALOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack);10251026    /* start the virtual machine *///调用成员函数startVMZygote进程中创建个虚拟机实例1027    JniInvocation jni_invocation;1028    jni_invocation.Init(NULL);1029    JNIEnv* env;1030    if (startVm(&mJavaVM, &env, zygote) != 0) {1031        return;1032    }1033    onVmCreated(env);10341035    /*1036     * Register android functions.1037     */1038    if (startReg(env) < 0) {//成员函数startReg在这个虚拟机实例中注册一系列JNI方法 1039        ALOGE("Unable to register all android natives\n");1040        return;1041    }10421043    /*1044     * We want to call main() with a String array with arguments in it.1045     * At present we have two arguments, the class name and an option string.1046     * Create an array to hold them.1047     */1048    jclass stringClass;1049    jobjectArray strArray;1050    jstring classNameStr;10511052    stringClass = env->FindClass("java/lang/String");1053    assert(stringClass != NULL);1054    strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);1055    assert(strArray != NULL);1056    classNameStr = env->NewStringUTF(className);1057    assert(classNameStr != NULL);1058    env->SetObjectArrayElement(strArray, 0, classNameStr);10591060    for (size_t i = 0; i < options.size(); ++i) {1061        jstring optionsStr = env->NewStringUTF(options.itemAt(i).string());1062        assert(optionsStr != NULL);1063        env->SetObjectArrayElement(strArray, i + 1, optionsStr);1064    }10651066    /*1067     * Start VM.  This thread becomes the main thread of the VM, and will1068     * not return until the VM exits.1069     */1070    char* slashClassName = toSlashClassName(className);1071    jclass startClass = env->FindClass(slashClassName);1072    if (startClass == NULL) {1073        ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);1074        /* keep going */1075    } else {1076        jmethodID startMeth = env->GetStaticMethodID(startClass, "main",1077            "([Ljava/lang/String;)V");1078        if (startMeth == NULL) {1079            ALOGE("JavaVM unable to find main() in '%s'\n", className);1080            /* keep going */1081        } else {1082            env->CallStaticVoidMethod(startClass, startMeth, strArray);1083            //调用com.android.internal.os.Zygotelnit类的静态成员函数main来进一步启动Zygote进程1084#if 01085            if (env->ExceptionCheck())1086                threadExitUncaughtException(env);1087#endif1088        }1089    }1090    free(slashClassName);10911092    ALOGD("Shutting down VM\n");1093    if (mJavaVM->DetachCurrentThread() != JNI_OK)1094        ALOGW("Warning: unable to detach main thread\n");1095    if (mJavaVM->DestroyJavaVM() != 0)1096        ALOGW("Warning: VM did not shut down cleanly\n");1097}


3.ZygoteInit.main

代码路径:/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

    (http://androidxref.com/8.0.0_r4/xref/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java)

671    public static void main(String argv[]) {672        ZygoteServer zygoteServer = new ZygoteServer();673674        // Mark zygote start. This ensures that thread creation will throw675        // an error.676        ZygoteHooks.startZygoteNoThreadCreation();677678        // Zygote goes into its own process group.679        try {680            Os.setpgid(0, 0);681        } catch (ErrnoException ex) {682            throw new RuntimeException("Failed to setpgid(0,0)", ex);683        }684685        try {686            // Report Zygote start time to tron unless it is a runtime restart687            if (!"1".equals(SystemProperties.get("sys.boot_completed"))) {688                MetricsLogger.histogram(null, "boot_zygote_init",689                        (int) SystemClock.elapsedRealtime());690            }691692            String bootTimeTag = Process.is64Bit() ? "Zygote64Timing" : "Zygote32Timing";693            BootTimingsTraceLog bootTimingsTraceLog = new BootTimingsTraceLog(bootTimeTag,694                    Trace.TRACE_TAG_DALVIK);695            bootTimingsTraceLog.traceBegin("ZygoteInit");696            RuntimeInit.enableDdms();697            // Start profiling the zygote initialization.698            SamplingProfilerIntegration.start();699700            boolean startSystemServer = false;701            String socketName = "zygote";702            String abiList = null;703            boolean enableLazyPreload = false;704            for (int i = 1; i < argv.length; i++) {705                if ("start-system-server".equals(argv[i])) {706                    startSystemServer = true;707                } else if ("--enable-lazy-preload".equals(argv[i])) {708                    enableLazyPreload = true;709                } else if (argv[i].startsWith(ABI_LIST_ARG)) {710                    abiList = argv[i].substring(ABI_LIST_ARG.length());711                } else if (argv[i].startsWith(SOCKET_NAME_ARG)) {712                    socketName = argv[i].substring(SOCKET_NAME_ARG.length());713                } else {714                    throw new RuntimeException("Unknown command line argument: " + argv[i]);715                }716            }717718            if (abiList == null) {719                throw new RuntimeException("No ABI list supplied.");720            }721            //Server端Socket是用来等待Activity管理服务ActivityManagerService请求Zygote进程创建新的应用程序进程的722            zygoteServer.registerServerSocket(socketName);//调用zygoteServer类的静态成员函数registerZygoteSocket来创建一个Server端Socket


执行preload函数来进行资源文件的预加载工作,加载类,加载资源文件,加载OPenGl,加载共享库,文本资源以及准备WebView.

723            // In some configurations, we avoid preloading resources and classes eagerly.724            // In such cases, we will preload things prior to our first fork.725            if (!enableLazyPreload) {726                bootTimingsTraceLog.traceBegin("ZygotePreload");727                EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,728                    SystemClock.uptimeMillis());729                preload(bootTimingsTraceLog);730                EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,731                    SystemClock.uptimeMillis());732                bootTimingsTraceLog.traceEnd(); // ZygotePreload733            } else {734                Zygote.resetNicePriority();735            }736737            // Finish profiling the zygote initialization.738            SamplingProfilerIntegration.writeZygoteSnapshot();739740            // Do an initial gc to clean up after startup741            bootTimingsTraceLog.traceBegin("PostZygoteInitGC");742            gcAndFinalize();743            bootTimingsTraceLog.traceEnd(); // PostZygoteInitGC744745            bootTimingsTraceLog.traceEnd(); // ZygoteInit746            // Disable tracing so that forked processes do not inherit stale tracing tags from747            // Zygote.748            Trace.setTracingEnabled(false);749750            // Zygote process unmounts root storage spaces.751            Zygote.nativeUnmountStorageOnInit();752753            // Set seccomp policy754            Seccomp.setPolicy();755756            ZygoteHooks.stopZygoteNoThreadCreation();757            //调用Zygotelnit类的静态成员函数startSystemServer来启动System进程,以便它可以将系统的关键服务启动起来758            if (startSystemServer) {759                startSystemServer(abiList, socketName, zygoteServer);760            }761762            Log.i(TAG, "Accepting command socket connections");763            zygoteServer.runSelectLoop(abiList);764765            zygoteServer.closeServerSocket();766        } catch (Zygote.MethodAndArgsCaller caller) {767            caller.run();768        } catch (Throwable ex) {769            Log.e(TAG, "System zygote died with exception", ex);770            zygoteServer.closeServerSocket();771            throw ex;772        }773    }774

通过参数判断是否启动systemServer,也就是通过刚刚我们记录下来的参数--start-system-server判定startSystemServer为true;接着通过调用registerZygoteSocket(socketName)函数来注册zygote套接字,进行进程间的通信


4.ZygoteInit.startSystemServer

代码路径:/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

(http://androidxref.com/8.0.0_r4/xref/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java)

590    /**591     * Prepare the arguments and fork for the system server process.592     */593    private static boolean startSystemServer(String abiList, String socketName, ZygoteServer zygoteServer)594            throws Zygote.MethodAndArgsCaller, RuntimeException {595        long capabilities = posixCapabilitiesAsBits(596            OsConstants.CAP_IPC_LOCK,597            OsConstants.CAP_KILL,598            OsConstants.CAP_NET_ADMIN,599            OsConstants.CAP_NET_BIND_SERVICE,600            OsConstants.CAP_NET_BROADCAST,601            OsConstants.CAP_NET_RAW,602            OsConstants.CAP_SYS_MODULE,603            OsConstants.CAP_SYS_NICE,604            OsConstants.CAP_SYS_PTRACE,605            OsConstants.CAP_SYS_TIME,606            OsConstants.CAP_SYS_TTY_CONFIG,607            OsConstants.CAP_WAKE_ALARM608        );609        /* Containers run without this capability, so avoid setting it in that case */610        if (!SystemProperties.getBoolean(PROPERTY_RUNNING_IN_CONTAINER, false)) {611            capabilities |= posixCapabilitiesAsBits(OsConstants.CAP_BLOCK_SUSPEND);612        }613        /* Hardcoded command line to start the system server */614        String args[] = {615            "--setuid=1000",616            "--setgid=1000",617            "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,1032,3001,3002,3003,3006,3007,3009,3010",618            "--capabilities=" + capabilities + "," + capabilities,619            "--nice-name=system_server",620            "--runtime-args",621            "com.android.server.SystemServer",622        };623        ZygoteConnection.Arguments parsedArgs = null;624625        int pid;626627        try {628            parsedArgs = new ZygoteConnection.Arguments(args);629            ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);630            ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);631632            /* Request to fork the system server process */633            pid = Zygote.forkSystemServer(634                    parsedArgs.uid, parsedArgs.gid,635                    parsedArgs.gids,636                    parsedArgs.debugFlags,637                    null,638                    parsedArgs.permittedCapabilities,639                    parsedArgs.effectiveCapabilities);640        } catch (IllegalArgumentException ex) {641            throw new RuntimeException(ex);642        }643644        /* For child process */645        if (pid == 0) {646            if (hasSecondZygote(abiList)) {647                waitForSecondaryZygote(socketName);648            }649650            zygoteServer.closeServerSocket();651            handleSystemServerProcess(parsedArgs);652        }653654        return true;655    }

准备系统服启动的参数,并通过forkSystemServer来创建系统服务进程,接着调用handleSystemServerProcess(parsedArgs)来进行系统服务的处理。


5.ZygoteServer.registerServerSocket

代码路径:/frameworks/base/core/java/com/android/internal/os/ZygoteServer.java

    (http://androidxref.com/8.0.0_r4/xref/frameworks/base/core/java/com/android/internal/os/ZygoteServer.java)

调用zygoteServer类的静态成员函数registerZygoteSocket来创建一个Server端Socket, Zygote进程将System进程启动起来之 后 ,就会在这个Server端Socket上等待Activity管理服务ActivityManagerService请求Zygote进程创建新的应用程序进程.

51    /**52     * Registers a server socket for zygote command connections53     *54     * @throws RuntimeException when open fails55     */56    void registerServerSocket(String socketName) {57        if (mServerSocket == null) {58            int fileDesc;59            final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;60            try {61                String env = System.getenv(fullSocketName);62                fileDesc = Integer.parseInt(env);63            } catch (RuntimeException ex) {64                throw new RuntimeException(fullSocketName + " unset or invalid", ex);65            }6667            try {68                FileDescriptor fd = new FileDescriptor();69                fd.setInt$(fileDesc);70                mServerSocket = new LocalServerSocket(fd);71            } catch (IOException ex) {72                throw new RuntimeException(73                        "Error binding to local socket '" + fileDesc + "'", ex);74            }75        }76    }


6.ZygoteServer.runSelectLoop

代码路径:/frameworks/base/core/java/com/android/internal/os/ZygoteServer.java

    (http://androidxref.com/8.0.0_r4/xref/frameworks/base/core/java/com/android/internal/os/ZygoteServer.java)

运行zygote进程的选择循环。 在发生时接受新的连接,并且一次从连接读取一次产生请求的价值。

128    /**129     * Runs the zygote process's select loop. Accepts new connections as130     * they happen, and reads commands from connections one spawn-request's131     * worth at a time.132     *133     * @throws Zygote.MethodAndArgsCaller in a child process when a main()134     * should be executed.135     */136    void runSelectLoop(String abiList) throws Zygote.MethodAndArgsCaller {137        ArrayList fds = new ArrayList();138        ArrayList peers = new ArrayList();139140        fds.add(mServerSocket.getFileDescriptor());141        peers.add(null);142143        while (true) {144            StructPollfd[] pollFds = new StructPollfd[fds.size()];145            for (int i = 0; i < pollFds.length; ++i) {146                pollFds[i] = new StructPollfd();147                pollFds[i].fd = fds.get(i);148                pollFds[i].events = (short) POLLIN;149            }150            try {151                Os.poll(pollFds, -1);152            } catch (ErrnoException ex) {153                throw new RuntimeException("poll failed", ex);154            }155            for (int i = pollFds.length - 1; i >= 0; --i) {156                if ((pollFds[i].revents & POLLIN) == 0) {157                    continue;158                }159                if (i == 0) {160                    ZygoteConnection newPeer = acceptCommandPeer(abiList);161                    peers.add(newPeer);162                    fds.add(newPeer.getFileDesciptor());163                } else {164                    boolean done = peers.get(i).runOnce(this);165                    if (done) {166                        peers.remove(i);167                        fds.remove(i);168                    }169                }170            }171        }172    }


7.ZygoteServer.closeServerSocket

代码路径:/frameworks/base/core/java/com/android/internal/os/ZygoteServer.java

    (http://androidxref.com/8.0.0_r4/xref/frameworks/base/core/java/com/android/internal/os/ZygoteServer.java)

关闭zygoteServer类的静态成员函数registerZygoteSocket创建的socket

96    /**97     * Close and clean up zygote sockets. Called on shutdown and on the98     * child's exit path.99     */100    void closeServerSocket() {101        try {102            if (mServerSocket != null) {103                FileDescriptor fd = mServerSocket.getFileDescriptor();104                mServerSocket.close();105                if (fd != null) {106                    Os.close(fd);107                }108            }109        } catch (IOException ex) {110            Log.e(TAG, "Zygote:  error closing sockets", ex);111        } catch (ErrnoException ex) {112            Log.e(TAG, "Zygote:  error closing descriptor", ex);113        }114115        mServerSocket = null;116    }

3.System启动过程

System进程是在ZygoteInit类的静态成员函数handleSystemServerProcess中开始启动的

          

 1.ZygoteInit.handleSystemServerProcess

代码路径:/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

    (http://androidxref.com/8.0.0_r4/xref/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java)

593    private static boolean startSystemServer(String abiList, String socketName, ZygoteServer zygoteServer)594            throws Zygote.MethodAndArgsCaller, RuntimeException {        ..........................................................643644        /* For child process */645        if (pid == 0) {646            if (hasSecondZygote(abiList)) {647                waitForSecondaryZygote(socketName);648            }649650            zygoteServer.closeServerSocket();651            handleSystemServerProcess(parsedArgs);652        }653654        return true;655    }
   
   
446    /**447     * Finish remaining work for the newly forked system server process.448     */449    private static void handleSystemServerProcess(450            ZygoteConnection.Arguments parsedArgs)451            throws Zygote.MethodAndArgsCaller {452453        // set umask to 0077 so new files and directories will default to owner-only permissions.454        Os.umask(S_IRWXG | S_IRWXO);455456        if (parsedArgs.niceName != null) {457            Process.setArgV0(parsedArgs.niceName);458        }459460        final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");461        if (systemServerClasspath != null) {462            performSystemServerDexOpt(systemServerClasspath);463            // Capturing profiles is only supported for debug or eng builds since selinux normally464            // prevents it.465            boolean profileSystemServer = SystemProperties.getBoolean(466                    "dalvik.vm.profilesystemserver", false);467            if (profileSystemServer && (Build.IS_USERDEBUG || Build.IS_ENG)) {468                try {469                    File profileDir = Environment.getDataProfilesDePackageDirectory(470                            Process.SYSTEM_UID, "system_server");471                    File profile = new File(profileDir, "primary.prof");472                    profile.getParentFile().mkdirs();473                    profile.createNewFile();474                    String[] codePaths = systemServerClasspath.split(":");475                    VMRuntime.registerAppInfo(profile.getPath(), codePaths);476                } catch (Exception e) {477                    Log.wtf(TAG, "Failed to set up system server profile", e);478                }479            }480        }481482        if (parsedArgs.invokeWith != null) {483            String[] args = parsedArgs.remainingArgs;484            // If we have a non-null system server class path, we'll have to duplicate the485            // existing arguments and append the classpath to it. ART will handle the classpath486            // correctly when we exec a new process.487            if (systemServerClasspath != null) {488                String[] amendedArgs = new String[args.length + 2];489                amendedArgs[0] = "-cp";490                amendedArgs[1] = systemServerClasspath;491                System.arraycopy(args, 0, amendedArgs, 2, args.length);492                args = amendedArgs;493            }494495            WrapperInit.execApplication(parsedArgs.invokeWith,496                    parsedArgs.niceName, parsedArgs.targetSdkVersion,497                    VMRuntime.getCurrentInstructionSet(), null, args);498        } else {499            ClassLoader cl = null;500            if (systemServerClasspath != null) {501                cl = createPathClassLoader(systemServerClasspath, parsedArgs.targetSdkVersion);502503                Thread.currentThread().setContextClassLoader(cl);504            }505506            /*507             * Pass the remaining arguments to SystemServer.508             */509            ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);510        }511512        /* should never reach here */513    }
   
System进程不需要使用这个Socket,因此,会调用zygoteServer类的静态成员函数closeServerSocket来关闭它。由于System进程复制了Zygote进程的地址空间,因此,它就会获得Zygote进程在启动过程中所创建的Socket。接下来调用ZygoteInit.zygoteInit,在ZygoteInit.zygoteInit中RuntimeInit类的静态成员函数zygoteInit来进一步启动System进程   


2.ZygoteInit.zygoteInit

代码路径:/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

 (http://androidxref.com/8.0.0_r4/xref/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java)

创建的系统服务剩余的工作,最后调用ZygoteInit.zygoteInit将剩余的参数传递到系统服务
829    public static final void zygoteInit(int targetSdkVersion, String[] argv,830            ClassLoader classLoader) throws Zygote.MethodAndArgsCaller {831        if (RuntimeInit.DEBUG) {832            Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");833        }834835        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");836        RuntimeInit.redirectLogStreams();//将System.out和System.err重定向到Android日志837838        RuntimeInit.commonInit();839        ZygoteInit.nativeZygoteInit();840        RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);841    }

3.RuntimeInit.applicationInit

代码路径:/frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
 (http://androidxref.com/8.0.0_r4/xref/frameworks/base/core/java/com/android/internal/os/RuntimeInit.java)

nativeZygoteInit()用于进程间通信的初始化操作,applicationInit函数用于服务的启动

289    protected static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)290            throws Zygote.MethodAndArgsCaller {291        // If the application calls System.exit(), terminate the process292        // immediately without running any shutdown hooks.  It is not possible to293        // shutdown an Android application gracefully.  Among other things, the294        // Android runtime shutdown hooks close the Binder driver, which can cause295        // leftover running threads to crash before the process actually exits.296        nativeSetExitWithoutCleanup(true);297298        // We want to be fairly aggressive about heap utilization, to avoid299        // holding on to a lot of memory that isn't needed.300        VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);301        VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);302303        final Arguments args;304        try {305            args = new Arguments(argv);306        } catch (IllegalArgumentException ex) {307            Slog.e(TAG, ex.getMessage());308            // let the process exit309            return;310        }311312        // The end of of the RuntimeInit event (see #zygoteInit).313        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);314315        // Remaining arguments are passed to the start class's static main316        invokeStaticMain(args.startClass, args.startArgs, classLoader);317    }

该函数主要是一些运行时的一些工作,同时调用invokeStaticMain来进行main函数的执行,看这个方法的注释,意思便是剩下的参数被传递,用于启动类的静态main函数。这里传递的类参数便是SystemServer类,所以这个函数的工作便是启动SystemServer的main函数

4.SystemServer.main

代码路径:/frameworks/base/services/java/com/android/server/SystemServer.java

 (http://androidxref.com/8.0.0_r4/xref/frameworks/base/services/java/com/android/server/SystemServer.java)

该函数位于frameworks/base/services/java/com/android/server/SystemServer.java类中,这里运行SystemServer的run函数,该函数设置环境变量,启动其他服务,

257     * The main entry point from zygote.258     */259    public static void main(String[] args) {260        new SystemServer().run();261    }
接着返回到ZygoteInit.java的main函数中,这个函数最后执行runSelectLoop函数,这里运行一个循环,接收新的连接,读取来自连接的命令


参考:

http://blog.csdn.net/gaugamela/article/details/52133186

https://www.jianshu.com/p/88e3a64d3a3e


更多相关文章

  1. 一款常用的 Squid 日志分析工具
  2. GitHub 标星 8K+!一款开源替代 ls 的工具你值得拥有!
  3. RHEL 6 下 DHCP+TFTP+FTP+PXE+Kickstart 实现无人值守安装
  4. Linux 环境下实战 Rsync 备份工具及配置 rsync+inotify 实时同步
  5. 一款霸榜 GitHub 的开源 Linux 资源监视器!
  6. Android(安卓)进程
  7. android中如何利用attrs和styles定义控件
  8. RN 与 Android(安卓)代码交互
  9. Android进程通信(IPC)之AIDL对象传递

随机推荐

  1. TextView 限制最大行数、最小行数、字数
  2. Android四种Activity的加载模式
  3. cocos2d-x 1.0.1 for Android(安卓)使用B
  4. 面试准备(待整理、未完待续。。)
  5. EditText所有属性详解
  6. Android开机广播和关机广播
  7. Android(安卓)中 PopupWindow的用法 汇总
  8. 有米Android(安卓)SDK开发者文档
  9. Android(安卓)O(8.0)创建桌面快捷方式
  10. 关于Android中的radioGroup选择