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

2024-07-23  本文已影响0人  忧零520

系统启动过程

启动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。

上一篇 下一篇

猜你喜欢

热点阅读