Launcher过程的启动
Launcher进程的启动
继System进程的启动流程第二部分之后,我们来分析Launcher进程的启动。
public class Process { ...... public static final int start(final String processClass, final String niceName, int uid, int gid, int[] gids, int debugFlags, String[] zygoteArgs) { if (supportsProcesses()) { try { return startViaZygote(processClass, niceName, uid, gid, gids, debugFlags, zygoteArgs); } catch (ZygoteStartFailedEx ex) { ...... } } else { ...... return 0; } } ...... }调用startViaZygote函数进一步操作。
public class Process { ...... 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); if ((debugFlags & Zygote.DEBUG_ENABLE_SAFEMODE) != 0) { argsForZygote.add("--enable-safemode"); } if ((debugFlags & Zygote.DEBUG_ENABLE_DEBUGGER) != 0) { argsForZygote.add("--enable-debugger"); } if ((debugFlags & Zygote.DEBUG_ENABLE_CHECKJNI) != 0) { argsForZygote.add("--enable-checkjni"); } if ((debugFlags & Zygote.DEBUG_ENABLE_ASSERT) != 0) { argsForZygote.add("--enable-assert"); } //TODO optionally enable debuger //argsForZygote.add("--enable-debugger"); // --setgroups is a comma-separated list if (gids != null && gids.length > 0) { StringBuilder sb = new StringBuilder(); sb.append("--setgroups="); int sz = gids.length; for (int i = 0; i < sz; i++) { if (i != 0) { sb.append(','); } sb.append(gids[i]); } argsForZygote.add(sb.toString()); } if (niceName != null) { argsForZygote.add("--nice-name=" + niceName); } argsForZygote.add(processClass); if (extraArgs != null) { for (String arg : extraArgs) { argsForZygote.add(arg); } } pid = zygoteSendArgsAndGetPid(argsForZygote); } } ...... }这个函数将创建进程的参数放到argsForZygote列表中去,如参数"--runtime-init"表示要为新创建的进程初始化运行时库,然后调用zygoteSendAndGetPid函数进一步操作。
public class Process { ...... private static int zygoteSendArgsAndGetPid(ArrayList<String> args) throws ZygoteStartFailedEx { int pid; openZygoteSocketIfNeeded(); try { /** * See com.android.internal.os.ZygoteInit.readArgumentList() * Presently the wire format to the zygote process is: * a) a count of arguments (argc, in essence) * b) a number of newline-separated argument strings equal to count * * After the zygote process reads these it will write the pid of * the child or -1 on failure. */ sZygoteWriter.write(Integer.toString(args.size()));//向Zygote进程发送通信数据 sZygoteWriter.newLine(); int sz = args.size(); for (int i = 0; i < sz; i++) { String arg = args.get(i); if (arg.indexOf('\n') >= 0) { throw new ZygoteStartFailedEx( "embedded newlines not allowed"); } sZygoteWriter.write(arg); sZygoteWriter.newLine(); } sZygoteWriter.flush(); // Should there be a timeout on this? pid = sZygoteInputStream.readInt(); if (pid < 0) { throw new ZygoteStartFailedEx("fork() failed"); } } catch (IOException ex) { ...... } return pid; } ...... }这里的sZygoteWriter是一个Socket写入流,是由openZygoteSocketIfNeeded函数打开的:
public class Process { ...... /** * 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++ ) { if (retry > 0) { try { Log.i("Zygote", "Zygote not up yet, sleeping..."); Thread.sleep(ZYGOTE_RETRY_MILLIS); } catch (InterruptedException ex) { // should never happen } } try { sZygoteSocket = new LocalSocket();//创建一个LocalSocket对象 sZygoteSocket.connect(new LocalSocketAddress(ZYGOTE_SOCKET, LocalSocketAddress.Namespace.RESERVED));//和设备文件/dev/socket/zygote绑定,就相当于与Zygote进程中名称为"zygote"的Socket建立了连接 sZygoteInputStream = new DataInputStream(sZygoteSocket.getInputStream());//输入流,以便获得Zygote进程发送过来的通信数据 sZygoteWriter = new BufferedWriter( new OutputStreamWriter( sZygoteSocket.getOutputStream()),//输出流,以便可以向Zygote进程发送通信数据 256); Log.i("Zygote", "Process: zygote socket opened"); sPreviousZygoteOpenFailed = false; break; } catch (IOException ex) { ...... } } ...... } ...... }
Process类有一个类型为LocalSocket的静态成员变量sZygoteSocket,它是Zygote进程中一个名称为"zygote"的Socket建立连接的。Zygote进程在启动时,会在内部创建一个名称为"zygote”的Socket,这个Socket是与设备文件/dev/socket/zygote绑定在一起的。
这个Socket由frameworks/base/core/java/com/android/internal/os/ZygoteInit.java文件中的ZygoteInit类在runSelectLoopMode函数侦听的。
当将数据通过Socket接口发送出去后,就会执行下面这个语句:
done = peers.get(index).runOnce();这里从peers.get(index)得到的是一个ZygoteConnection对象,表示一个Socket连接,因此,接下来就是调用ZygoteConnection.runOnce函数进一步处理了。
class ZygoteConnection { ...... boolean runOnce() throws ZygoteInit.MethodAndArgsCaller { String args[]; Arguments parsedArgs = null; FileDescriptor[] descriptors; try { args = readArgumentList(); descriptors = mSocket.getAncillaryFileDescriptors(); } catch (IOException ex) { ...... return true; } ...... /** the stderr of the most recent request, if avail */ PrintStream newStderr = null; if (descriptors != null && descriptors.length >= 3) { newStderr = new PrintStream( new FileOutputStream(descriptors[2])); } int pid; try { parsedArgs = new Arguments(args); applyUidSecurityPolicy(parsedArgs, peer); applyDebuggerSecurityPolicy(parsedArgs); applyRlimitSecurityPolicy(parsedArgs, peer); applyCapabilitiesSecurityPolicy(parsedArgs, peer); int[][] rlimits = null; if (parsedArgs.rlimits != null) { rlimits = parsedArgs.rlimits.toArray(intArray2d); } pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, parsedArgs.debugFlags, rlimits); } catch (IllegalArgumentException ex) { ...... } catch (ZygoteSecurityException ex) { ...... } if (pid == 0) { // in child handleChildProc(parsedArgs, descriptors, newStderr); // should never happen return true; } else { /* pid != 0 */ // in parent...pid of < 0 means failure return handleParentProc(pid, descriptors, parsedArgs); } } ...... }真正创建进程的地方就是在这里了:
pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, parsedArgs.debugFlags, rlimits);详情请参考Dalvik虚拟机进程和线程的创建过程分析。
applyRlimitSecurityPolicy用于安全检查,只有System进程和root进程才能请求Zygote进程,让它创建进程。
private static void applyRlimitSecurityPolicy( Arguments args, Credentials peer) throws ZygoteSecurityException { int peerUid = peer.getUid(); if (!(peerUid == 0 || peerUid == Process.SYSTEM_UID)) { // All peers with UID other than root or SYSTEM_UID if (args.rlimits != null) { throw new ZygoteSecurityException( "This UID may not specify rlimits."); } } }还有一处安全问题需要注意,现在uid为0,但是在forkAndSpecializeCommon中fork后,又自降uid了。
/* * Utility routine to fork zygote and specialize the child process. */ static pid_t forkAndSpecializeCommon(const u4* args, bool isSystemServer) { pid_t pid; uid_t uid = (uid_t) args[0]; gid_t gid = (gid_t) args[1]; ArrayObject* gids = (ArrayObject *)args[2]; u4 debugFlags = args[3]; ArrayObject *rlimits = (ArrayObject *)args[4]; int64_t permittedCapabilities, effectiveCapabilities; if (isSystemServer) { /* * Don't use GET_ARG_LONG here for now. gcc is generating code * that uses register d8 as a temporary, and that's coming out * scrambled in the child process. b/3138621 */ //permittedCapabilities = GET_ARG_LONG(args, 5); //effectiveCapabilities = GET_ARG_LONG(args, 7); permittedCapabilities = args[5] | (int64_t) args[6] << 32; effectiveCapabilities = args[7] | (int64_t) args[8] << 32; } else { permittedCapabilities = effectiveCapabilities = 0; } if (!gDvm.zygote) { ...... return -1; } ...... pid = fork(); if (pid == 0) { int err; ...... err = setgroupsIntarray(gids); ...... err = setrlimitsFromArray(rlimits); ...... err = setgid(gid); ...... err = setuid(uid); ...... err = setCapabilities(permittedCapabilities, effectiveCapabilities); ...... enableDebugFeatures(debugFlags); ...... gDvm.zygote = false; if (!dvmInitAfterZygote()) { ...... dvmAbort(); } } else if (pid > 0) { /* the parent process */ } return pid; }返回到runOnce,我们先来看父进程Zygote的执行路线。
private boolean handleParentProc(int pid, FileDescriptor[] descriptors, Arguments parsedArgs) { if(pid > 0) { // Try to move the new child into the peer's process group. try { ZygoteInit.setpgid(pid, ZygoteInit.getpgid(peer.getPid())); } catch (IOException ex) { // This exception is expected in the case where // the peer is not in our session // TODO get rid of this log message in the case where // getsid(0) != getsid(peer.getPid()) Log.i(TAG, "Zygote: setpgid failed. This is " + "normal if peer is not in our session"); } } try { if (descriptors != null) { for (FileDescriptor fd: descriptors) { ZygoteInit.closeDescriptor(fd); } } } catch (IOException ex) { Log.e(TAG, "Error closing passed descriptors in " + "parent process", ex); } try { mSocketOutStream.writeInt(pid);//向System进程写回pid } catch (IOException ex) { Log.e(TAG, "Error reading from command socket", ex); return true; } /* * If the peer wants to use the socket to wait on the * newly spawned process, then we're all done. */ if (parsedArgs.peerWait) { try { mSocket.close(); } catch (IOException ex) { Log.e(TAG, "Zygote: error closing sockets", ex); } return true; } return false; }还记得,zygoteSendArgsAndGetPid中:
pid = sZygoteInputStream.readInt();System进程在等待获得Zygote进程发送过来的通信数据,此时可以返回了。
返回后System进程就可以调用Looper.loop()启动子线程的消息处理机制。如下所示:
class ServerThread extends Thread { @Override public void run() { ...... Looper.prepare(); ...... try { ...... Slog.i(TAG, "Activity Manager"); context = ActivityManagerService.main(factoryTest); ...... Slog.i(TAG, "Package Manager"); pm = PackageManagerService.main(context, factoryTest != SystemServer.FACTORY_TEST_OFF);//以后分析 ActivityManagerService.setSystemProcess(); ...... ((ActivityManagerService)ActivityManagerNative.getDefault()) .systemReady(new Runnable() { public void run() { } }); ...... } catch (RuntimeException e) { Slog.e("System", "Failure starting core service", e); } ...... Looper.loop(); Slog.d(TAG, "System ServerThread is exiting!"); } }
Zygote进程同时也处理完,在Socket端口继续等待请求。
class ZygoteConnection { ...... private void handleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors, PrintStream newStderr) throws ZygoteInit.MethodAndArgsCaller { ...... if (parsedArgs.runtimeInit) { RuntimeInit.zygoteInit(parsedArgs.remainingArgs); } else { ...... } } ...... }
public class RuntimeInit { ...... public static final void zygoteInit(String[] argv) throws ZygoteInit.MethodAndArgsCaller { // TODO: Doing this here works, but it seems kind of arbitrary. Find // a better place. The goal is to set it up for applications, but not // tools like am. System.setOut(new AndroidPrintStream(Log.INFO, "System.out")); System.setErr(new AndroidPrintStream(Log.WARN, "System.err")); commonInit(); zygoteInitNative(); int curArg = 0; for ( /* curArg */ ; curArg < argv.length; curArg++) { String arg = argv[curArg]; if (arg.equals("--")) { curArg++; break; } else if (!arg.startsWith("--")) { break; } else if (arg.startsWith("--nice-name=")) { String niceName = arg.substring(arg.indexOf('=') + 1); Process.setArgV0(niceName); } } if (curArg == argv.length) { Slog.e(TAG, "Missing classname argument to RuntimeInit!"); // let the process exit return; } // Remaining arguments are passed to the start class's static main String startClass = argv[curArg++]; String[] startArgs = new String[argv.length - curArg]; System.arraycopy(argv, curArg, startArgs, 0, startArgs.length); invokeStaticMain(startClass, startArgs); } ...... }zygoteInitNative开启了子线程的Binder线程池,请参考System进程的启动流程第一部分。
invokeStaticMain也参考System进程的启动流程第一部分。开始执行android.app.ActivityThread类的main函数。
public final class ActivityThread { ...... public static final void main(String[] args) { SamplingProfilerIntegration.start(); Process.setArgV0("<pre-initialized>"); Looper.prepareMainLooper(); if (sMainThreadHandler == null) { sMainThreadHandler = new Handler(); } ActivityThread thread = new ActivityThread(); thread.attach(false); if (false) { Looper.myLooper().setMessageLogging(new LogPrinter(Log.DEBUG, "ActivityThread")); } Looper.loop(); if (Process.supportsProcesses()) { throw new RuntimeException("Main thread loop unexpectedly exited"); } thread.detach(); String name = (thread.mInitialApplication != null) ? thread.mInitialApplication.getPackageName() : "<unknown>"; Slog.i(TAG, "Main thread of " + name + " is now exiting"); } ...... }从这里我们可以看出,这个函数首先会在进程中创建一个ActivityThread对象:
ActivityThread thread = new ActivityThread();然后进入主线程消息循环中:
Looper.prepareMainLooper(); Looper.loop();
下一节Home界面的启动中我们将分析,如下代码
ActivityThread thread = new ActivityThread(); thread.attach(false);
版权声明:本文为博主原创文章,未经博主允许不得转载。