您的位置:首页 > 移动开发 > Android开发

Android8.0.0-r4系统的启动过程

2018-02-24 23:57 387 查看
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);//创建文件并挂载
964
965    if (is_first_stage) {
966        boot_clock::time_point start_time = boot_clock::now();
967
968        // Clear the umask.
969        umask(0); //清除屏蔽字(file mode creation mask),保证新建的目录的访问权限不受屏蔽字影响
970
971        // Get the basic filesystem setup we need put together in the initramdisk
972        // 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 actually
990        // talk to the outside world...
991        InitKernelLogging(argv);//内核log初始化
992
993        LOG(INFO) << "init first stage started!";
994
995        if (!DoFirstStageMount()) {
996            LOG(ERROR) << "Failed to mount required partitions early ...";
997            panic();
998        }
999
1000        SetInitAvbVersionInRecovery();//判断是否为recovery模式
1001
1002        // Set up SELinux, loading the SELinux policy.
1003        selinux_initialize(true);//初始化selinux
1004
1005        // We're in the kernel domain, so re-exec init to transition to the init domain now
1006        // that the SELinux policy has been loaded.
1007        if (restorecon("/init") == -1) {
1008            PLOG(ERROR) << "restorecon failed";
1009            security_failure();
1010        }
1011
1012        setenv("INIT_SECOND_STAGE", "true", 1);
1013
1014        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);
1017
1018        char* path = argv[0];
1019        char* args[] = { path, nullptr };
1020        execv(path, args);
1021
1022        // execv() only returns if an error happened, in which case we
1023        // panic and never fall through this conditional.
1024        PLOG(ERROR) << "execv(\"" << path << "\") failed";
1025        security_failure();
1026    }
1027
1028    // At this point we're in the second stage of init.
1029    InitKernelLogging(argv);
1030    LOG(INFO) << "init second stage started!";
1031
1032    // Set up a session keyring that all processes will have access to. It
1033    // will hold things like FBE encryption keys. No process should override
1034    // its session keyring.
1035    keyctl(KEYCTL_GET_KEYRING_ID, KEY_SPEC_SESSION_KEYRING, 1);
1036
1037    // 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文件是否可读写、创建等
1039
1040    property_init();// 初始化属性域 --> 定义于system/core/init/property_service.cpp
1041
1042    // 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中的属性总是优先于内核命令行
1046
1047    // Propagate the kernel variables to internal variables
1048    // used by init as well as the current required properties.
1049    export_kernel_boot_props();//将内核变量传播给init使用的内部变量以及当前所需的属性
1050
1051    // 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匹配
1058
1059    // Clean up our environment.
1060    unsetenv("INIT_SECOND_STAGE");
1061    unsetenv("INIT_STARTED_AT");
1062    unsetenv("INIT_SELINUX_TOOK");
1063    unsetenv("INIT_AVB_VERSION");
1064
1065    // Now set up SELinux for second stage.
1066    selinux_initialize(false);//加载SELinux策略, 后面有一些初始化文件上下文的操作等
1067    selinux_restore_context();
1068
1069    epoll_fd = epoll_create1(EPOLL_CLOEXEC);
1070    if (epoll_fd == -1) {
1071        PLOG(ERROR) << "epoll_create1 failed";
1072        exit(1);
1073    }
1074
1075    signal_handler_init();///初始化子进程退出的信号处理过程
1076
1077    property_load_boot_defaults();//加载/default.prop文件
1078    export_oem_lock_status();
1079    start_property_service();//启动属性服务器(通过socket通信)
1080    set_usb_controller();
1081
1082    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<ServiceParser>());//设置对应的解析函数 “service”块以关键字“service”开始,表示启动某个进程的方式和参数
1087    parser.AddSectionParser("on", std::make_unique<ActionParser>());//“action”块以关键字“on”开始,表示一堆命令的集合
1088    parser.AddSectionParser("import", std::make_unique<ImportParser>()); //“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    }
1103
1104    // Turning this on and letting the INFO logging be discarded adds 0.2s to
1105    // Nexus 9 boot time, so it's disabled by default.
1106    if (false) parser.DumpState();
1107
1108    ActionManager& am = ActionManager::GetInstance();
1109
1110    am.QueueEventTrigger("early-init");
1111
1112    // 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");
1120
1121    // Trigger all the boot actions to get us started.
1122    am.QueueEventTrigger("init");
1123
1124    // Repeat mix_hwrng_into_linux_rng in case /dev/hw_random or /dev/random
1125    // wasn't ready immediately after wait_for_coldboot_done
1126    am.QueueBuiltinAction(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");
1127
1128    // 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    }
1135
1136    // 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的无限循环来建立子进程
1138
1139    while (true) {
1140        // By default, sleep until something happens.
1141        int epoll_timeout_ms = -1;//以下决定epoll_timeout_ms的时间,将影响while循环的间隔
1142
1143        if (!(waiting_for_prop || ServiceManager::GetInstance().IsWaitingForExec())) {
1144            am.ExecuteOneCommand();
1145        }
1146        if (!(waiting_for_prop || ServiceManager::GetInstance().IsWaitingForExec())) {
1147            restart_processes();
1148
1149            // 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            }
1154
1155            // If there's more work to do, wake up again immediately.
1156            if (am.HasMoreCommands()) epoll_timeout_ms = 0;
1157        }
1158
1159        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    }
1167
1168    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πor2.zygote启动过程在init.rc中,early-init相关启动的services和actions。基本上是恢复某些文件或文件夹的安全上下文,然后调用init_zygote32_64.rc文件中的命令启动zygote1service 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<int>(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<String8> 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();316317 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<String8>& 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 *///调用成员函数startVM在Zygote进程中创建一个虚拟机实例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<FileDescriptor> fds = new ArrayList<FileDescriptor>();138        ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();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创建的socket96    /**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 {
..........................................................
643
644        /* For child process */
645        if (pid == 0) {
646            if (hasSecondZygote(abiList)) {
647                waitForSecondaryZygote(socketName);
648            }
649
650            zygoteServer.closeServerSocket();
651            handleSystemServerProcess(parsedArgs);
652        }
653
654        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 {
452
453        // set umask to 0077 so new files and directories will default to owner-only permissions.
454        Os.umask(S_IRWXG | S_IRWXO);
455
456        if (parsedArgs.niceName != null) {
457            Process.setArgV0(parsedArgs.niceName);
458        }
459
460        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 normally
464            // 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        }
481
482        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 the
485            // existing arguments and append the classpath to it. ART will handle the classpath
486            // 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            }
494
495            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);
502
503                Thread.currentThread().setContextClassLoader(cl);
504            }
505
506            /*
507             * Pass the remaining arguments to SystemServer.
508             */
509            ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
510        }
511
512        /* 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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: