美文网首页
Zygote接收到AMS消息到启动ActivityThread流

Zygote接收到AMS消息到启动ActivityThread流

作者: 忧零520 | 来源:发表于2024-07-23 22:46 被阅读0次

    系统启动过程

    启动Zygote进程:
    启动过程开始于Zygote进程,当启动一个应用时,Zygote进程会被复用以创建新的应用进程。

    这里是ZygoteInit.main的主要作用,它是Zygote进程的入口:

    public class ZygoteInit {
        public static void main(String argv[]) {
            // ... 省略的一些前期初始化代码
    
            // 启动系统服务进程
            if (startSystemServer) {
                startSystemServer(forkedProcesses);
            }
    
            // 进入Zygote的主循环
            Runnable caller;
            try {
                caller = zygoteServer.runSelectLoop();
            } catch (Throwable ex) {
              // ... 处理异常
            }
    
            // 运行子进程初始化代码
            if (caller != null) {
                caller.run();
            }
        }
    }
    1、Zygote连接处理:
    Zygote进程在初始化后会进入一个循环,等待来自ActivityManagerService(AMS)的进程启动请求。这是在runSelectLoop中处理的。
    
    ZygoteServer.runSelectLoop 在后台等待连接请求:
    
    public class ZygoteServer {
        Runnable runSelectLoop() {
            while (true) {
                // 等待AMS连接
                ZygoteConnection connection = acceptCommandPeer();
                return connection.processOneCommand(); // 这里实际上是处理一个命令
            }
        }
    }
    2、处理启动命令:
    在接收到启动请求后,ZygoteConnection.processOneCommand 方法负责处理实际启动参数。
    
    public class ZygoteConnection {
        Runnable processOneCommand() {
            // 解析启动参数
            Arguments args = readArgumentList();
    
            // 调用Zygote来fork新进程
            Zygote.forkAndSpecialize(...);
    
            if (pid == 0) {
                // 子进程执行到这里
                return handleChildProc(args, descriptors, childPipeFd, newStderr);
            } else {
                // 父进程(Zygote进程)执行到这里
                ...
            }
        }
    }
    这 就是说,handleChildProc 方法在子进程中被调用,这里新启动的进程会完成初始化:
    
    3. handleChildProc
    handleChildProc 负责处理子进程的初始化。
    
    public class ZygoteConnection {
        private Runnable handleChildProc(Arguments parsedArgs) {
            // 初始化子进程
            return RuntimeInit.wrapperInit(parsedArgs);
        }
    }
    4. RuntimeInit.wrapperInit
    RuntimeInit.wrapperInit 是实际启动应用进程的方法。
    
    public class RuntimeInit {
        public static Runnable wrapperInit(Arguments args) {
            return applicationInit(args);
        }
        private static Runnable applicationInit(Arguments args) {
            return invokeStaticMain(args.startClass, args.startArgs, null);
        }
        protected static Runnable invokeStaticMain(String className, String[] argv, ClassLoader classLoader) {
            // 反射调用main方法
            Class<?> cl;
            try {
                cl = Class.forName(className);
                Method m = cl.getMethod("main", new Class[] { String[].class });
                m.invoke(null, new Object[]{argv});
            } catch (Exception ex) {
                throw new RuntimeException(ex);
            }
            return null;
        }
    }
    5. ActivityThread.main
    以上步骤最终会调用到ActivityThread.main方法,这是实际应用进程的入口。
    
    public class ActivityThread {
        public static void main(String[] args) {
            // 主线程初始化
            Looper.prepareMainLooper();
            ActivityThread thread = new ActivityThread();
            thread.attach(false);
            Looper.loop();
        }
    }
    

    总结

    整个调用链从Zygote接收启动参数到涉及到的主要过程如下:
    ZygoteInit.main: 启动进程,并进入等待循环。
    ZygoteServer.runSelectLoop: 等待并处理启动请求。
    ZygoteConnection.processOneCommand: 解析并fork新的进程。
    RuntimeInit.wrapperInit: 完成子进程进一步初始化。
    RuntimeInit.applicationInit: 通过反射调用指定类的main方法。
    ActivityThread.main: 启动应用主线程。

    接下来看看AMS是怎么传输Socket数据给Zygote的

    在ActivityManagerService(AMS)中,有关启动应用进程并通过Socket请求发送给Zygote的部分,主要是通过startProcessLocked方法来实现。这个方法会调用Process.start方法,并通过Zygote发送启动请求。在启动参数中传递了android.app.ActivityThread。

    具体的流程如下:

    1. ActivityManagerService.startProcessLocked
    ActivityManagerService的startProcessLocked方法负责启动新进程:
    
    public class ActivityManagerService {
        private boolean startProcessLocked(ProcessRecord app, ...) {
            ...
            // 调用Process.start来启动进程
            Process.ProcessStartResult startResult = Process.start(
                    "android.app.ActivityThread", // 这里指定类名
                    app.processName, ...);
            ...
        }
    }
    2. Process.start
    Process.start方法负责创建并启动一个新的应用进程:
    
    public class Process {
        public static ProcessStartResult start(
                String processClass, // 这里是传入的 "android.app.ActivityThread"
                String niceName,
                ...
                ) {
            ...
            try {
                return startViaZygote(processClass, niceName, ...);
            } catch (RuntimeException e) {
                ...
            }
        }
    
        private static ProcessStartResult startViaZygote(
                String processClass,
                String niceName,
                ...
                ) {
            ...
            // 创建启动参数列表
            ArrayList<String> argsForZygote = new ArrayList<String>();
    
            // 传递启动组件类名
            argsForZygote.add("--runtime-args");
            argsForZygote.add("--setuid=" + uid);
            argsForZygote.add("--setgid=" + gid);
            argsForZygote.add("-classpath");
            argsForZygote.add("--nice-name=" + niceName);
            argsForZygote.add(processClass); // 传入的类名
    
            // 调用Zygote来启动进程
            ProcessStartResult result = ZygoteProcess.zygoteSendArgsAndGetResult(
                    openZygoteSocketIfNeeded(abi), argsForZygote);
            ...
            return result;
        }
    }
    3. ZygoteProcess.zygoteSendArgsAndGetResult
    这个方法通过Socket将启动参数发送给Zygote进程:
    
    public class ZygoteProcess {
        public Process.ProcessStartResult zygoteSendArgsAndGetResult(
                ZygoteState zygoteState, ArrayList<String> args)
                throws ZygoteStartFailedEx {
            try {
                // 获取Zygote进程的Socket连接
                DataOutputStream zygoteWriter = zygoteState.mZygoteOutputWriter;
    
                // 发送启动参数
                for (String arg : args) {
                    zygoteWriter.writeBytes(arg + "\n");
                }
    
                // 获取启动结果
                ProcessStartResult result = new ProcessStartResult();
                result.pid = zygoteState.mZygoteInputStream.readInt();
                ...
                return result;
            } catch (IOException ex) {
                throw new ZygoteStartFailedEx(ex);
            }
        }
    }
    传递给Zygote的参数
    从上述代码可以看到,Process.start方法最终构建了一个参数列表argsForZygote,其中包括要启动的类名android.app.ActivityThread,并通过ZygoteProcess.zygoteSendArgsAndGetResult发送到Zygote进程。
    
    4. 接受请求并启动进程的Zygote代码
    回到之前的细节:
    
    ZygoteServer.runSelectLoop
    Zygote进程在启动后,会进入一个循环等待AMS的请求:
    
    public class ZygoteServer {
        Runnable runSelectLoop() {
            while (true) {
                ZygoteConnection connection = acceptCommandPeer();
                return connection.processOneCommand();
            }
        }
    }
    ZygoteConnection.processOneCommand
    在接受到启动请求后,Zygote进程通过processOneCommand方法处理请求:
    
    public class ZygoteConnection {
        Runnable processOneCommand() {
            // 读取并解析参数
            Arguments args = readArgumentList();
            // Fork新的进程
            int pid = Zygote.forkAndSpecialize(args);
            if (pid == 0) {
                // 子进程处理
                return handleChildProc(args);
            } else {
                // 父进程处理
                ...
            }
        }
    }
    

    总结
    总结来说,关于传递类名android.app.ActivityThread的调用链如下:

    ActivityManagerService.startProcessLocked: 调用Process.start方法,传入类名android.app.ActivityThread。
    Process.start: 调用startViaZygote,构建参数列表并调用ZygoteProcess.zygoteSendArgsAndGetResult。
    ZygoteProcess.zygoteSendArgsAndGetResult: 通过Socket将启动参数发给Zygote进程。
    ZygoteServer.runSelectLoop: 接受并处理启动请求。
    ZygoteConnection.processOneCommand: 解析启动参数并fork新进程。
    handleChildProc: 初始化新进程,最终调用RuntimeInit.zygoteInit,并反射调用ActivityThread.main。

    相关文章

      网友评论

          本文标题:Zygote接收到AMS消息到启动ActivityThread流

          本文链接:https://www.haomeiwen.com/subject/nosuhjtx.html