if (is_first_stage) { // Clear the umask,与Linux系统权限有关 umask(0);
// Get the basic filesystem setup we need put together in the initramdisk // on / and then we'll let the rc file figure out the rest. mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755"); mkdir("/dev/pts", 0755); // ...
InitKernelLogging(argv);
LOG(INFO) << "init first stage started!";
if (!DoFirstStageMount()) { LOG(ERROR) << "Failed to mount required partitions early ..."; panic(); }
// Set up SELinux(Security-Enhanced Linux), loading the SELinux policy. selinux_initialize(true);
// We're in the kernel domain, so re-exec init to transition to the init domain now // that the SELinux policy has been loaded. // 按selinux policy要求,重新设置init文件属性 if (restorecon("/init") == -1) { // 失败的话会reboot PLOG(ERROR) << "restorecon failed"; security_failure(); }
// execv() only returns if an error happened, in which case we // panic and never fall through this conditional. PLOG(ERROR) << "execv(\"" << path << "\") failed"; security_failure(); }
// 第二阶段:用户态 InitKernelLogging(argv); LOG(INFO) << "init second stage started!";
// Now set up SELinux for second stage. selinux_initialize(false); selinux_restore_context();
signal_handler_init();
// 开启属性服务 start_property_service();
// 解析init.rc // ...
while (true) { // 默认会休眠直到有事件唤醒 int epoll_timeout_ms = -1;
if (!(waiting_for_prop || ServiceManager::GetInstance().IsWaitingForExec())) { am.ExecuteOneCommand(); } // 重启一些挂掉的进程,例如Zygote if (!(waiting_for_prop || ServiceManager::GetInstance().IsWaitingForExec())) { restart_processes(); // If there's a process that needs restarting, wake up in time for that. if (process_needs_restart_at != 0) { epoll_timeout_ms = (process_needs_restart_at - time(nullptr)) * 1000; if (epoll_timeout_ms < 0) epoll_timeout_ms = 0; }
// If there's more work to do, wake up again immediately. if (am.HasMoreCommands()) epoll_timeout_ms = 0; }
epoll_event ev; int nr = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd, &ev, 1, epoll_timeout_ms)); if (nr == -1) { PLOG(ERROR) << "epoll_wait failed"; } elseif (nr == 1) { ((void (*)()) ev.data.ptr)(); } }
on early-init on init on property:sys.boot_from_charger_mode=1 on load_persist_props_action on firmware_mounts_complete on late-init on post-fs // mount file system start logd mount rootfs rootfs / ro remount mount rootfs rootfs / shared rec mount none /mnt/runtime/default /storage slave bind rec // ... // ... on post-fs-data // mount /data/ // 启动 logd start logd // 启动 vold, 用于管理Android外部存储介质的后台进程,包括SD卡的插拔等 start vold // ... // ... on boot // ... class_start core
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote class main priority -20 user root group root readproc reserved_disk socket zygote stream 660 root system onrestart write /sys/android_power/request_state wake onrestart write /sys/power/state on onrestart restart audioserver onrestart restart cameraserver onrestart restart media onrestart restart netd onrestart restart wificond writepid /dev/cpuset/foreground/tasks
service zygote_secondary /system/bin/app_process32 -Xzygote /system/bin --zygote --socket-name=zygote_secondary --enable-lazy-preload class main priority -20 user root group root readproc reserved_disk socket zygote_secondary stream 660 root system onrestart restart zygote writepid /dev/cpuset/foreground/tasks
通过 init_parser.cpp 完成整个 service 解析工作,此处就不详细展开讲解析过程。
// --zygote : Start in zygote mode // --start-system-server : Start the system server. // --application : Start in application (stand alone, non zygote) mode. // --nice-name : The nice name for this process. bool zygote = false; bool startSystemServer = false; bool application = false; String8 niceName; String8 className;
Vector<String8> args; if (!className.isEmpty()) { // We're not in zygote mode // 需要传递给RuntimeInit的唯一参数是application参数,剩余的args传递给启动类main args.add(application ? String8("application") : String8("tool")); runtime.setClassNameAndArgs(className, argc - i, argv + i); } else { // We're in zygote mode. maybeCreateDalvikCache();
if (startSystemServer) { args.add(String8("start-system-server")); }
char prop[PROP_VALUE_MAX]; if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) { LOG_ALWAYS_FATAL("app_process: Unable to determine ABI list from property %s.", ABI_LIST_PROPERTY); return11; }
// In zygote mode, pass all remaining arguments to the zygote // main() method. for (; i < argc; ++i) { args.add(String8(argv[i])); } }
if (!niceName.isEmpty()) { runtime.setArgv0(niceName.string(), true/* setProcName */); }
if (zygote) { runtime.start("com.android.internal.os.ZygoteInit", args, zygote); } elseif (className) { runtime.start("com.android.internal.os.RuntimeInit", args, zygote); } else { fprintf(stderr, "Error: no class name or --zygote supplied.\n"); app_usage(); LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied."); } }
// The select loop returns early in the child process after a fork and // loops forever in the zygote. caller = zygoteServer.runSelectLoop(abiList); } catch (Throwable ex) { Log.e(TAG, "System zygote died with exception", ex); throw ex; } finally { zygoteServer.closeServerSocket(); }
// We're in the child process and have exited the select loop. Proceed to execute the command. if (caller != null) { caller.run(); } }
// Sets the SIGCHLD handler back to default behavior in zygote children. staticvoidUnsetChldSignalHandler(){ structsigactionsa; memset(&sa, 0, sizeof(sa)); sa.sa_handler = SIG_DFL;
staticvoidSigChldHandler(int/*signal_number*/){ pid_t pid; int status;
while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { if (pid == gSystemServerPid) { ALOGE("Exit zygote because system server (%d) has terminated", pid); kill(getpid(), SIGKILL); } } }
// In some cases after launching an app we need to access device identifiers, // therefore register the device identifier policy before the activity manager. mSystemServiceManager.startService(DeviceIdentifiersPolicyService.class);
// Now that we have the bare essentials of the OS up and running, take // note that we just booted, which might send out a rescue party if // we're stuck in a runtime restart loop. RescueParty.noteBoot(mSystemContext);
// Package manager isn't started yet; need to use SysProp not hardware feature if (SystemProperties.getBoolean("config.enable_sidekick_graphics", false)) { mSystemServiceManager.startService(WEAR_SIDEKICK_SERVICE_CLASS); }
// We need the default display before we can initialize the package manager. mSystemServiceManager.startBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);
// 当设备正在加密时,仅运行core apps String cryptState = SystemProperties.get("vold.decrypt"); if (ENCRYPTING_STATE.equals(cryptState)) { Slog.w(TAG, "Detected encryption in progress - only parsing core apps"); mOnlyCore = true; } elseif (ENCRYPTED_STATE.equals(cryptState)) { Slog.w(TAG, "Device encrypted - only parsing core apps"); mOnlyCore = true; }
while (true) { StructPollfd[] pollFds = new StructPollfd[fds.size()]; for (int i = 0; i < pollFds.length; ++i) { pollFds[i] = new StructPollfd(); pollFds[i].fd = fds.get(i); pollFds[i].events = (short) POLLIN; } try { Os.poll(pollFds, -1); } catch (ErrnoException ex) { thrownew RuntimeException("poll failed", ex); } for (int i = pollFds.length - 1; i >= 0; --i) { if ((pollFds[i].revents & POLLIN) == 0) { continue; }
if (i == 0) { ZygoteConnection newPeer = acceptCommandPeer(abiList); peers.add(newPeer); fds.add(newPeer.getFileDesciptor()); } else { try { ZygoteConnection connection = peers.get(i); final Runnable command = connection.processOneCommand(this); // 通过mIsForkChild变量控制父进程接着死循环/子进程返回command if (mIsForkChild) { // We're in the child. We should always have a command to run at this // stage if processOneCommand hasn't called "exec". if (command == null) { thrownew IllegalStateException("command == null"); }
return command; } else { // We're in the server - we should never have any commands to run. if (command != null) { thrownew IllegalStateException("command != null"); }
// Sets the SIGCHLD handler back to default behavior in zygote children. staticvoidUnsetChldSignalHandler(){ structsigactionsa; memset(&sa, 0, sizeof(sa)); sa.sa_handler = SIG_DFL; }
staticvoidSigChldHandler(int/*signal_number*/){ while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { // If the just-crashed process is the system_server, bring down zygote // so that it is restarted by init and system server will be restarted // from there. if (pid == gSystemServerPid) { ALOGE("Exit zygote because system server (%d) has terminated", pid); kill(getpid(), SIGKILL); } } }
// 清理所有必须立即关闭的描述符 if (!DetachDescriptors(env, fdsToClose, &error_msg)) { fail_fn(error_msg); } // Re-open all remaining open file descriptors so that they aren't shared // with the zygote across a fork. if (!gOpenFdTable->ReopenOrDetach(&error_msg)) { fail_fn(error_msg); } MountEmulatedStorage(uid, mount_external, use_native_bridge, &error_msg);
// If this zygote isn't root, it won't be able to create a process group, // since the directory is owned by root. if (!is_system_server && getuid() == 0) { int rc = createProcessGroup(uid, getpid()); } // selinux上下文 rc = selinux_android_setcontext(uid, is_system_server, se_info_c_str, se_name_c_str);
if (se_name_c_str == NULL && is_system_server) { se_name_c_str = "system_server"; } if (se_name_c_str != NULL) { SetThreadName(se_name_c_str); }
// Unset the SIGCHLD handler, but keep ignoring SIGHUP (rationale in SetSignalHandlers). UnsetChldSignalHandler(); // 等价于调用zygote.callPostForkChildHooks() env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, runtime_flags, is_system_server, is_child_zygote, instructionSet); } return pid; }
在 Linux 系统中 fork 子进程会复制父进程用户空间的数据到子进程(copy-on-write),然后复制当前线程到子进程,而父进程中的其它线程在子进程中都”蒸发”了。如果在fork之前,一个线程持有了某个锁,然后另外一个线程调用了fork创建子进程,在子进程中持有那个锁的线程却”蒸发”了,从子进程的角度来看,这个锁被“永久”的上锁了,因为它的持有者“蒸发”了。如果子进程中的任何一个线程对这个已经被持有的锁进行lock操作,就会发生死锁。