Android8.0.0-r4系统的启动过程
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 *///调用成员函数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 ArrayListfds = 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
更多相关文章
- 一款常用的 Squid 日志分析工具
- GitHub 标星 8K+!一款开源替代 ls 的工具你值得拥有!
- RHEL 6 下 DHCP+TFTP+FTP+PXE+Kickstart 实现无人值守安装
- Linux 环境下实战 Rsync 备份工具及配置 rsync+inotify 实时同步
- 一款霸榜 GitHub 的开源 Linux 资源监视器!
- Android(安卓)进程
- android中如何利用attrs和styles定义控件
- RN 与 Android(安卓)代码交互
- Android进程通信(IPC)之AIDL对象传递