on boot # basic network init ifup lo hostname localhost domainname localdomain
# 省略部分源码 service ril-daemon /system/bin/rild socket rild stream 660 root radio socket rild-debug stream 660 radio system user root group radio cache inet misc audio sdcard_rw
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server socket zygote stream 666 onrestart write /sys/android_power/request_state wake onrestart write /sys/power/state on onrestart restart media onrestart restart netd
service media /system/bin/mediaserver user media group system audio camera graphics inet net_bt net_bt_admin net_raw ioprio rt 4 # 省略部分源码
if (properties_inited()) notify_service_state(svc->name, "running"); }
intmain(int argc, char **argv) { int fd_count = 0; structpollfdufds[4]; char *tmpdev; char* debuggable; char tmp[32]; int property_set_fd_init = 0; int signal_fd_init = 0; int keychord_fd_init = 0;
if (!strcmp(basename(argv[0]), "ueventd")) return ueventd_main(argc, argv);
/* clear the umask */ 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. */ mkdir("/dev", 0755); mkdir("/proc", 0755); mkdir("/sys", 0755);
/* We must have some place other than / to create the * device nodes for kmsg and null, otherwise we won't * be able to remount / read-only later on. * Now that tmpfs is mounted on /dev, we can actually * talk to the outside world. */ open_devnull_stdio(); log_init(); INFO("reading config file\n"); // 这里开始解析init.rc文件,方法实现在同级目录的init_parser.c里 init_parse_config_file("/init.rc");
/* pull the kernel commandline and ramdisk properties file in */ import_kernel_cmdline(0);
get_hardware_name(hardware, &revision); snprintf(tmp, sizeof(tmp), "/init.%s.rc", hardware); init_parse_config_file(tmp); // 省略部分源码 /* execute all the boot actions to get us started */ action_for_each_trigger("early-boot", action_add_queue_tail); // 这个阶段对应init.rc 里的 on boot,会把 zygote进程启动起来 action_for_each_trigger("boot", action_add_queue_tail); /* run all property triggers based on current state of the properties */ queue_builtin_action(queue_property_triggers_action, "queue_propety_triggers"); // 省略部分源码 for(;;) { int nr, i, timeout = -1; // 省略部分源码 nr = poll(ufds, fd_count, timeout); if (nr <= 0) continue;
for (i = 0; i < fd_count; i++) { if (ufds[i].revents == POLLIN) { if (ufds[i].fd == get_property_set_fd()) handle_property_set_fd(); elseif (ufds[i].fd == get_keychord_fd()) handle_keychord(); elseif (ufds[i].fd == get_signal_fd()) handle_signal(); } } }
//其实很简单,就是把service解析出来,放到一个全局的service_list中 staticvoid *parse_service(struct parse_state *state, int nargs, char **args) { structservice *svc; if (nargs < 3) { parse_error(state, "services must have a name and a program\n"); return0; } if (!valid_name(args[1])) { parse_error(state, "invalid service name '%s'\n", args[1]); return0; }
svc = service_find_by_name(args[1]); if (svc) { parse_error(state, "ignored duplicate definition of service '%s'\n", args[1]); return0; }
/* execute all the boot actions to get us started */ action_for_each_trigger("early-boot", action_add_queue_tail); action_for_each_trigger("boot", action_add_queue_tail); /* run all property triggers based on current state of the properties */ queue_builtin_action(queue_property_triggers_action, "queue_propety_triggers");
/* * sets argv0 to as much of newArgv0 as will fit */ static void setArgv0(const char *argv0, const char *newArgv0) { strlcpy(const_cast<char *>(argv0), newArgv0, strlen(argv0)); }
int main(int argc, const char* const argv[]) {
// 省略部分源码 AppRuntime runtime; const char *arg; const char *argv0; // Everything up to '--' or first non '-' arg goes to the vm int i = runtime.addVmArguments(argc, argv); // Next arg is startup classname or "--zygote" if (i < argc) { arg = argv[i++]; if (0 == strcmp("--zygote", arg)) { bool startSystemServer = (i < argc) ? strcmp(argv[i], "--start-system-server") == 0 : false; setArgv0(argv0, "zygote"); //将进程名设置成zygote set_process_name("zygote"); // 核心逻辑,开始调用了ZygoteInit类方法,会走到AppRuntime.onStarted runtime.start("com.android.internal.os.ZygoteInit", startSystemServer); } } //省略部分源码 }
/* * Start the Android runtime. This involves starting the virtual machine * and calling the "static void main(String[] args)" method in the class * named by "className". */ void AndroidRuntime::start(const char* className, const bool startSystemServer) { // 省略部分逻辑 // 核心逻辑第一步:启动VM虚拟机 /* start the virtual machine */ if (startVm(&mJavaVM, &env) != 0) goto bail;
/* * Register android functions. */ // 核心逻辑第二步:为很多Android中的Java类注册相应的jni方法 if (startReg(env) < 0) { LOGE("Unable to register all android natives\n"); goto bail; }
/* * We want to call main() with a String array with arguments in it. * At present we only have one argument, the class name. Create an * array to hold it. */ jclass stringClass; jobjectArray strArray; jstring classNameStr; jstring startSystemServerStr;
/** * Finish remaining work for the newly forked system server process. */ private static void handleSystemServerProcess( ZygoteConnection.Arguments parsedArgs) throws ZygoteInit.MethodAndArgsCaller {
closeServerSocket();
/* * Pass the remaining arguments to SystemServer. * "--nice-name=system_server com.android.server.SystemServer" */ RuntimeInit.zygoteInit(parsedArgs.remainingArgs); /* should never reach here */ }
/** * Prepare the arguments and fork for the system server process. */ private static boolean startSystemServer() throws MethodAndArgsCaller, RuntimeException { /* Hardcoded command line to start the system server */ String args[] = { "--setuid=1000", "--setgid=1000", "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,3001,3002,3003", "--capabilities=130104352,130104352", "--runtime-init", "--nice-name=system_server", "com.android.server.SystemServer", }; ZygoteConnection.Arguments parsedArgs = null;
int pid;
try { parsedArgs = new ZygoteConnection.Arguments(args);
/* * Enable debugging of the system process if *either* the command line flags * indicate it should be debuggable or the ro.debuggable system property * is set to "1" */ int debugFlags = parsedArgs.debugFlags; if ("1".equals(SystemProperties.get("ro.debuggable"))) debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
/* Request to fork the system server process */ pid = Zygote.forkSystemServer( parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, debugFlags, null, parsedArgs.permittedCapabilities, parsedArgs.effectiveCapabilities); } catch (IllegalArgumentException ex) { throw new RuntimeException(ex); }
/* For child process */ if (pid == 0) { handleSystemServerProcess(parsedArgs); }
public static final void zygoteInit(String[] argv) throws ZygoteInit.MethodAndArgsCaller { // 省略部分代码 // Remaining arguments are passed to the start class's static main
LOGI("System server: starting Android services.\n"); runtime->callStatic("com/android/server/SystemServer", "init2"); // If running in our own process, just go into the thread // pool. Otherwise, call the initialization finished // func to let this process continue its initilization. if (proc->supportsProcesses()) { LOGI("System server: entering thread pool.\n"); ProcessState::self()->startThreadPool(); IPCThreadState::self()->joinThreadPool(); LOGI("System server: exiting thread pool.\n"); } return NO_ERROR; }
发现绕了一圈,又调回来了SystemServer的init2方法
1 2 3 4 5 6
public static final void init2() { Slog.i(TAG, "Entered the Android system server!"); Thread thr = new ServerThread(); thr.setName("android.server.ServerThread"); thr.start(); }
// The AccountManager must come before the ContentService try { Slog.i(TAG, "Account Manager"); ServiceManager.addService(Context.ACCOUNT_SERVICE, new AccountManagerService(context)); } catch (Throwable e) { Slog.e(TAG, "Failure starting Account Manager", e); }
Slog.i(TAG, "Battery Service"); battery = new BatteryService(context); ServiceManager.addService("battery", battery);
Slog.i(TAG, "Lights Service"); lights = new LightsService(context);
Slog.i(TAG, "Vibrator Service"); ServiceManager.addService("vibrator", new VibratorService(context));
// only initialize the power service after we have started the // lights service, content providers and the battery service. power.init(context, lights, ActivityManagerService.getDefault(), battery);
Slog.i(TAG, "Alarm Manager"); AlarmManagerService alarm = new AlarmManagerService(context); ServiceManager.addService(Context.ALARM_SERVICE, alarm);
public static final int start(final String processClass, final String niceName, int uid, int gid, int[] gids, int debugFlags, String[] zygoteArgs){ //去掉部分代码 return startViaZygote(processClass, niceName, uid, gid, gids, debugFlags, zygoteArgs); }
private static int startViaZygote(final String processClass, final String niceName, final int uid, final int gid, final int[] gids, int debugFlags, String[] extraArgs) throws ZygoteStartFailedEx { int pid; //去掉部分代码 synchronized(Process.class) { ArrayList<String> argsForZygote = new ArrayList<String>(); // --runtime-init, --setuid=, --setgid=, // and --setgroups= must go first argsForZygote.add("--runtime-init"); argsForZygote.add("--setuid=" + uid); argsForZygote.add("--setgid=" + gid); //注意我们传进来的processClass是android.app.ActivityThread argsForZygote.add(processClass);
if (extraArgs != null) { for (String arg : extraArgs) { argsForZygote.add(arg); } } pid = zygoteSendArgsAndGetPid(argsForZygote); }
return pid; } //直接打开socket和zygote进程通信 private static int zygoteSendArgsAndGetPid(ArrayList<String> args) throws ZygoteStartFailedEx { int pid; openZygoteSocketIfNeeded(); //省略部分代码 return pid; }
/** * Tries to open socket to Zygote process if not already open. If * already open, does nothing. May block and retry. */ private static void openZygoteSocketIfNeeded() throws ZygoteStartFailedEx {
int retryCount;
if (sPreviousZygoteOpenFailed) { /* * If we've failed before, expect that we'll fail again and * don't pause for retries. */ retryCount = 0; } else { retryCount = 10; }
/* * See bug #811181: Sometimes runtime can make it up before zygote. * Really, we'd like to do something better to avoid this condition, * but for now just wait a bit... */ for (int retry = 0 ; (sZygoteSocket == null) && (retry < (retryCount + 1)) ; retry++ ) {
/** * Runs the zygote process's select loop. Accepts new connections as * they happen, and reads commands from connections one spawn-request's * worth at a time. * * @throws MethodAndArgsCaller in a child process when a main() should * be executed. */ private static void runSelectLoopMode() throws MethodAndArgsCaller { ArrayList<FileDescriptor> fds = new ArrayList(); ArrayList<ZygoteConnection> peers = new ArrayList(); FileDescriptor[] fdArray = new FileDescriptor[4];
int loopCount = GC_LOOP_COUNT; while (true) { int index;
/* * Call gc() before we block in select(). * It's work that has to be done anyway, and it's better * to avoid making every child do it. It will also * madvise() any free memory as a side-effect. * * Don't call it every time, because walking the entire * heap is a lot of overhead to free a few hundred bytes. */ if (loopCount <= 0) { gc(); loopCount = GC_LOOP_COUNT; } else { loopCount--; }
try { fdArray = fds.toArray(fdArray); index = selectReadable(fdArray); } catch (IOException ex) { throw new RuntimeException("Error in select()", ex); }
if (index < 0) { throw new RuntimeException("Error in select()"); } else if (index == 0) { ZygoteConnection newPeer = acceptCommandPeer(); peers.add(newPeer); fds.add(newPeer.getFileDesciptor()); } else { boolean done; //核心逻辑 done = peers.get(index).runOnce();
if (done) { peers.remove(index); fds.remove(index); } } } }
/** * Reads one start command from the command socket. If successful, * a child is forked and a {@link ZygoteInit.MethodAndArgsCaller} * exception is thrown in that child while in the parent process, * the method returns normally. On failure, the child is not * spawned and messages are printed to the log and stderr. Returns * a boolean status value indicating whether an end-of-file on the command * socket has been encountered. * * @return false if command socket should continue to be read from, or * true if an end-of-file has been encountered. * @throws ZygoteInit.MethodAndArgsCaller trampoline to invoke main() * method in child process */ boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
/* * Close the socket, unless we're in "peer wait" mode, in which * case it's used to track the liveness of this process. */ if (parsedArgs.peerWait) { try { ZygoteInit.setCloseOnExec(mSocket.getFileDescriptor(), true); sPeerWaitSocket = mSocket; } catch (IOException ex) { Log.e(TAG, "Zygote Child: error setting peer wait " + "socket to be close-on-exec", ex); } } else { closeSocket(); ZygoteInit.closeServerSocket(); }