写点什么

Android Framework 学习笔记(六)应用程序进程启动过程

发布于: 2021 年 11 月 06 日

private static ProcessStartResult zygoteSendArgsAndGetResult(ZygoteState zygoteState, ArrayList<String> args) throws ZygoteStartFailedEx {


try {


// Throw early if any of the arguments are malformed. This means we can


// avoid writing a partial response to the zygote.


int sz = args.size();


for (int i = 0; i < sz; i++) {


if (args.get(i).indexOf('\n') >= 0) {


throw new ZygoteStartFailedEx("embedded newlines not allowed");


}


}


final BufferedWriter writer = zygoteState.writer;


final DataInputStream inputStream = zygoteState.inputStream;


writer.write(Integer.toString(args.size()));


writer.newLine();


for (int i = 0; i < sz; i++) {


String arg = args.get(i);


writer.write(arg);


writer.newLine();


}


writer.flush();


// Should there be a timeout on this?


ProcessStartResult result = new Process


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


StartResult();


result.pid = inputStream.readInt();


result.usingWrapper = inputStream.readBoolean();


if (result.pid < 0) {


throw new ZygoteStartFailedEx("fork() failed");


}


return result;


} catch (IOException ex) {


zygoteState.close();


throw new ZygoteStartFailedEx(ex);


}


}


zygoteSendArgsAndGetResult 函数主要做的就是将传入的应用进程的启动参数 argsForZygote 写入到 ZygoteState 中,结合上文我们知道 ZygoteState 其实是由 openZygoteSocketIfNeeded 函数返回的,那么我们接着来看 openZygoteSocketIfNeeded 函数。


Process#openZygoteSocketIfNeeded()


private static ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {


if (primaryZygoteState == null || primaryZygoteState.isClosed()) {


try {


primaryZygoteState = ZygoteState.connect(ZYGOTE_SOCKET); //1


} catch (IOException ioe) {


throw new ZygoteStartFailedEx("Error connecting to primary zygote", ioe);


}


}


if (primaryZygoteState.matches(abi)) {


return primaryZygoteState;


}


// The primary zygote didn't match. Try the secondary.


if (secondaryZygoteState == null || secondaryZygoteState.isClosed()) {


try {


secondaryZygoteState = ZygoteState.connect(SECONDARY_ZYGOTE_SOCKET); //2


} catch (IOException ioe) {


throw new ZygoteStartFailedEx("Error connecting to secondary zygote", ioe);


}


}


if (secondaryZygoteState.matches(abi)) {


return secondaryZygoteState;


}


throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi);


}


在之前讲 Zygote 进程启动过程时我们得知,在 Zygote 的 main 函数中会创建 name 为“zygote”的 Server 端 Socket。


注释 1 处会调用 ZygoteState 的 connect 函数与名称为 ZYGOTE_SOCKET 的 Socket 建立连接,这里 ZYGOTE_SOCKET 的值为“zygote”。


注释 2 处如果连接 name 为“zygote”的 Socket 返回的 primaryZygoteState 与当前的 abi 不匹配,则会连接 name 为“zygote_secondary”的 Socket。这两个 Socket 区别就是:name 为”zygote”的 Socket 是运行在 64 位 Zygote 进程中的,而 name 为“zygote_secondary”的 Socket 则运行在 32 位 Zygote 进程中。既然应用程序进程是通过 Zygote 进程 fock 产生的,当要连接 Zygote 中的 Socket 时,也需要保证位数的一致。


接收请求并创建应用程序进程




Socket 进行连接成功并匹配 abi 后会返回 ZygoteState 类型对象,我们在分析 zygoteSendArgsAndGetResult 函数中讲过,会将应用进程的启动参数 argsForZygote 写入到 ZygoteState 中,这样 Zygote 进程就会收到一个创建新的应用程序进程的请求,我们回到 ZygoteInit 的 main 函数。


frameworks/base/core/java/com/android/internal/os/ZygoteInit.java


ZygoteInit#main()


public static void main(String argv[]) {


...


try {


String socketName = "zygote";


/*注册 Zygote 用的 Socket/


registerZygoteSocket(socketName); //1


//预加载类和资源


preload(); //2


...


//启动 SystemServer 进程


if (startSystemServer) {


startSystemServer(abiList, socketName); //3


}


//监听 socket,启动新的应用进程


runSelectLoop(abiList); //4


closeServerSocket();


} catch (MethodAndArgsCaller caller) {


//通过反射调用 SystemServer#main()


caller.run();


} catch (RuntimeException ex) {


Log.e(TAG, "Zygote died with exception", ex);


closeServerSocket();


throw ex;


}


}


注释 1 处通过 registerZygoteSocket 函数来创建一个 Server 端的 Socket,这个 name 为”zygote”的 Socket 用来等待 AMS 来请求 Zygote 来创建新的应用程序进程。


注释 2 处用来预加载类和资源。


注释 3 处用来启动 SystemServer 进程,这样系统的关键服务也会由 SystemServer 进程启动起来。


注释 4 处调用 runSelectLoop 函数来等待 AMS 的请求。


ZygoteInit#runSelectLoop()


private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {


ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();


ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();


fds.add(sServerSocket.getFileDescriptor()); //1


peers.add(null);


while (true) {


StructPollfd[] pollFds = new StructPollfd[fds.size()];


for (int i = 0; i < pollFds.length; ++i) { //2


pollFds[i] = new StructPollfd();


pollFds[i].fd = fds.get(i);


pollFds[i].events = (short) POLLIN;


}


try {


Os.poll(pollFds, -1);


} catch (ErrnoException ex) {


throw new RuntimeException("poll failed", ex);


}


for (int i = pollFds.length - 1; i >= 0; --i) { //3


if ((pollFds[i].revents & POLLIN) == 0) {


continue;


}


if (i == 0) {


ZygoteConnection newPeer = acceptCommandPeer(abiList); //4


peers.add(newPeer);


fds.add(newPeer.getFileDesciptor());


} else {


boolean done = peers.get(i).runOnce(); //5


if (done) {


peers.remove(i);


fds.remove(i);


}


}


}


}


}


private static ZygoteConnection acceptCommandPeer(String abiList) {


try {


return new ZygoteConnection(sServerSocket.accept(), abiList);


} catch (IOException ex) {


...


}


}


注释 1 处中的 sServerSocket 就是我们在 registerZygoteSocket 函数中创建的服务端 Socket,调用 sServerSocket.getFileDescriptor()用来获得该 Socket 的 fd 字段的值并添加到 fd 列表 fds 中。接下来无限循环用来等待 AMS 请求 Zygote 进程创建新的应用程序进程。


注释 2 处通过遍历将 fds 存储的信息转移到 pollFds 数组中。


注释 3 处对 pollFds 进行遍历。


注释 4 如果 i==0 则说明服务端 Socket 与客户端连接上,也就是当前 Zygote 进程与 AMS 建立了连接,则通过 acceptCommandPeer 函数得到 ZygoteConnection 类并添加到 Socket 连接列表 peers 中,接着将该 ZygoteConnection 的 fd 添加到 fd 列表 fds 中,以便可以接收到 AMS 发送过来的请求。


注释 5 如果 i 的值大于 0,则说明 AMS 向 Zygote 进程发送了一个创建应用进程的请求,则调用 ZygoteConnection 的 runOnce 函数来创建一个新的应用程序进程。并在成功创建后将这个连接从 Socket 连接列表 peers 和 fd 列表 fds 中清除。


frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java


ZygoteConnection#runOnce()


boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {


String args[];


Arguments parsedArgs = null;


FileDescriptor[] descriptors;


try {


args = readArgumentList(); //1


descriptors = mSocket.getAncillaryFileDescriptors();


} catch (IOException ex) {


Log.w(TAG, "IOException on command socket " + ex.getMessage());


closeSocket();


return true;


}


...


try {


parsedArgs = new Arguments(args);//2


...


//3


pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,


parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,


parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet,


parsedArgs.appDataDir);


} catch (ErrnoException ex) {


....


}


try {


//4


if (pid == 0) {


// in child


IoUtils.closeQuietly(serverPipeFd);


serverPipeFd = null;


handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);


return true;


} else {


// in parent...pid of < 0 means failure


IoUtils.closeQuietly(childPipeFd);


childPipeFd = null;


return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);


}


} finally {


IoUtils.closeQuietly(childPipeFd);


IoUtils.closeQuietly(serverPipeFd);


}


}


注释 1 处调用 readArgumentList 函数来获取应用程序进程的启动参数。注释 2 处将 readArgumentList 函数返回的字符串封装到 Arguments 对象 parsedArgs 中。


注释 3 处调用 Zygote 的 forkAndSpecialize 函数来创建应用程序进程,参数为 parsedArgs 中存储的应用进程启动参数,返回值为 pid。


注释 4 处 forkAndSpecialize 函数主要是通过 fork 当前进程来创建一个子进程的,如果 pid 等于 0,则说明是在新创建的子进程中执行的,就会调用 handleChildProc 函数来启动这个子进程也就是应用程序进程。


ZygoteConnection#handleChildProc()


private void handleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)


throws ZygoteInit.MethodAndArgsCaller {


...


//1


if (parsedArgs.invokeWith != null) {


WrapperInit.execApplication(parsedArgs.invokeWith,


parsedArgs.niceName, parsedArgs.targetSdkVersion,


VMRuntime.getCurrentInstructionSet(),


pipeFd, parsedArgs.remainingArgs);


} else {


RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,


parsedArgs.remainingArgs, null /* classLoader */);


}


}


}


注释 1 处由于 parsedArgs.invokeWith 属性默认为 null,最后调用 RuntimeInit.zygoteInit 函数。


frameworks/base/core/java/com/android/internal/os/RuntimeInit.java


RuntimeInit#zygoteInit()


public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)


throws ZygoteInit.MethodAndArgsCaller {


if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");


Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "RuntimeInit");


redirectLogStreams();


commonInit();


nativeZygoteInit(); //1


applicationInit(targetSdkVersion, argv, classLoader); //2


}


注释 1 处会在新创建的应用程序进程中创建 Binder 线程池。


注释 2 处调用了 applicationInit 函数。


RuntimeInit#applicationInit()


private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)


throws ZygoteInit.MethodAndArgsCaller {


...


// 初始化虚拟机环境


VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);


VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);


final Arguments args;


try {


args = new Arguments(argv);


} catch (IllegalArgumentException ex) {


Slog.e(TAG, ex.getMessage());


// let the process exit


return;


}


// Remaining arguments are passed to the start class's static main


invokeStaticMain(args.startClass, args.startArgs, classLoader); //1


}


注释 1 处 applicationInit 函数中主要调用了 invokeStaticMain 函数,需要注意的是第一个参数 args.startClass,这里指的就是前面赋值的 android.app.ActivityThread。


RuntimeInit#invokeStaticMain()


private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader) throws ZygoteInit.MethodAndArgsCaller {


Class<?> cl;


try {


cl = Class.forName(className, true, classLoader); //1


} catch (ClassNotFoundException ex) {


throw new RuntimeException("Missing class when invoking static main " + className, ex);


}


Method m;


try {


// 获取 main 方法


m = cl.getMethod("main", new Class[] { String[].class }); //2


} catch (NoSuchMethodException ex) {


throw new RuntimeException("Missing static main on " + className, ex);


} catch (SecurityException ex) {


throw new RuntimeException("Problem getting static main on " + className, ex);


}


// 判断修饰符


int modifiers = m.getModifiers(); //3


if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {


throw new RuntimeException("Main method is not public and static on " + className);


}


/*


  • This throw gets caught in ZygoteInit.main(), which responds

  • by invoking the exception's run() method. This arrangement

  • clears up all the stack frames that were required in setting

  • up the process.


*/


throw new ZygoteInit.MethodAndArgsCaller(m, argv); //4


}


注释 1 处通过反射来获得 android.app.ActivityThread 类。


注释 2 处来获得 ActivityThread 的 main 函数。


注释 3 判断修饰符,必须是 static 而且必须是 public 类型。


注释 4 将找到的 main 函数传入到 MethodAndArgsCaller 异常中并抛出该异常。这个异常在 ZygoteInit#main()方法中捕获。这么做的作用是清除应用程序进程创建过程的调用栈。


ZygoteInit#main()


public static void main(String argv[]) {


try {


...


startSystemServer(abiList, socketName);


...


} catch (MethodAndArgsCaller caller) {


caller.run(); //1


}


}


在注释 1 处调用了 MethodAndArgsCaller 的 run 函数。


MethodAndArgsCaller


public static class MethodAndArgsCaller extends Exception


implements Runnable {


/** method to call */


private final Method mMethod;


/** argument array */


private final String[] mArgs;


public MethodAndArgsCaller(Method method, String[] args) {


mMethod = method;


mArgs = args;


}


public void run() {


try {


mMethod.invoke(null, new Object[] { mArgs }); //1


} catch (IllegalAccessException ex) {


throw new RuntimeException(ex);


} catch (InvocationTargetException ex) {


Throwable cause = ex.getCause();


if (cause instanceof RuntimeException) {


throw (RuntimeException) cause;


} else if (cause instanceof Error) {


throw (Error) cause;


}


throw new RuntimeException(ex);


}


}


}


注释 1 处通过反射调用了 android.app.ActivityThread#main(String[] args)。至此,Zygote 进程 fork 出 ActivityThread 进程,并成功调用 ActivityThread#main()。


frameworks/base/core/java/android/app/ActivityThread.java


ActivityThread#main()


public static void main(String[] args) {


Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");


SamplingProfilerIntegration.start();


...


Looper.prepareMainLooper();//1


ActivityThread thread = new ActivityThread();//2


thread.attach(false); //3


if (sMainThreadHandler == null) {


sMainThreadHandler = thread.getHandler(); //4


}


if (false) {


Looper.myLooper().setMessageLogging(new


LogPrinter(Log.DEBUG, "ActivityThread"));


}


Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);


Looper.loop();//5


throw new RuntimeException("Main thread loop unexpectedly exited");


}


注释 1 处在当前应用程序进程中创建消息循环。


注释 2 处创建 ActivityThread 实例。


注释 4 处从 ActivityThread 获取 handler,这样就将 ActivityThread 关联到 Looper 和 MessageQueue 了。


注释 5 处调用 Looper 的 loop,使得 Looper 开始工作,开始处理消息。可以看出,系统在应用程序进程启动完成后,就会创建一个消息循环,用来方便的使用 Android 的异步消息处理机制。


关于 Android 的异步消息处理机制大家可以参考我这篇文章:Android 异步消息处理机制:Looper、Handler、Message。这里就不多说了。


如果你看过Framework学习(三)SyetemServer进程启动过程


这篇文章,你肯定会发现创建应用程序进程和创建 SyetemServer 进程的步骤如此类似,其实他们都是通过 Zygote 进程 fork 自身来实现的,当然步骤差不多了。唯一区别是一个最终调用到 SyetemServer 的 main 函数,另一个最终调用到 ActivityThread 的 main 函数。


之前说过:在 Android 系统中,启动四大组件中的任何一个都可以启动应用程序。但实际上应用程序入口方法只有 ActivityThread#main()一个。接着看 ActivityThread#main()方法。


注释 3 处调用了 ActivityThread#attach(false)。


ActivityThread#attach()


final ApplicationThread mAppThread = new ApplicationThread();


private void attach(boolean system) {


sCurrentActivityThread = this;


mSystemThread = system;


if (!system) {


...


final IActivityManager mgr = ActivityManagerNative.getDefault();


try {


mgr.attachApplication(mAppThread); //1


} catch (RemoteException ex) {


// Ignore


}


...


}


...


}


前面文章分析过 AMS 中的 Binder 机制:ActivityManagerNative.getDefault(),返回的其实是 AMS。注释 1 其实调用的是 AMS 的 attachApplication 方法。


frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java


ActivityManagerService#attachApplication()


public final void attachApplication(IApplicationThread thread) {


synchronized (this) {


int callingPid = Binder.getCallingPid();


final long origId = Binder.clearCallingIdentity();


attachApplicationLocked(thread, callingPid); //1


Binder.restoreCallingIdentity(origId);


}


}


注释 1 调用了两个参数的 attachApplicationLocked()方法


ActivityManagerService#attachApplicationLocked()


private final boolean attachApplicationLocked(IApplicationThread thread,int pid) {


...


if (normalMode) {


try {


if (mStackSupervisor.attachApplicationLocked(app)) { //1


didSomething = true;


}


} catch (Exception e) {


Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);


badApp = true;


}


}


...


}


注释 1 调用 ActivityStackSupervisor 的 attachApplicationLocked 方法。


frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java


ActivityStackSupervisor#attachApplicationLocked()


boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {


final String processName = app.processName;


boolean didSomething = false;


for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {


ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;


for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {

评论

发布
暂无评论
Android Framework学习笔记(六)应用程序进程启动过程