Android Framwork ---App进程启动(上)

87 阅读4分钟
/frameworks/base/core/java/com/android/internal/os/
    - ZygoteInit.java
    - ZygoteConnection.java
    - RuntimeInit.java
    - Zygote.java

/frameworks/base/core/java/android/os/Process.java
/frameworks/base/core/jni/com_android_internal_os_Zygote.cpp
/frameworks/base/core/jni/AndroidRuntime.cpp
/frameworks/base/cmds/app_process/App_main.cpp (内含AppRuntime类)

/bionic/libc/bionic/fork.cpp
/bionic/libc/bionic/pthread_atfork.cpp

/libcore/dalvik/src/main/java/dalvik/system/ZygoteHooks.java
/art/runtime/native/dalvik_system_ZygoteHooks.cc
/art/runtime/Runtime.cc
/art/runtime/Thread.cc
/art/runtime/signal_catcher.cc

进程创建概况

image.png

  1. App发起进程:当从桌面启动应用,则发起进程便是Launcher所在进程;当从某App内启动远程进程,则发送进程便是该App所在进程。发起进程先通过binder发送消息给system_server进程;
  2. system_server进程:调用Process.start()方法,通过socket向zygote进程发送创建新进程的请求;
  3. zygote进程:在执行ZygoteInit.main()后便进入runSelectLoop()循环体内,当有客户端连接时便会执行ZygoteConnection.runOnce()方法,再经过层层调用后fork出新的应用进程;
  4. 新进程:执行handleChildProc方法,最后调用ActivityThread.main()方法。

一. system_server发起请求

1. Process.start

public static final ProcessStartResult start(final String processClass, final String niceName, int uid, int gid, int[] gids, int debugFlags, int mountExternal, int targetSdkVersion, String seInfo, String abi, String instructionSet, String appDataDir, String[] zygoteArgs) {
    try {
        return startViaZygote(processClass, niceName, uid, gid, gids,
                debugFlags, mountExternal, targetSdkVersion, seInfo,
                abi, instructionSet, appDataDir, zygoteArgs);
    } catch (ZygoteStartFailedEx ex) {
        throw new RuntimeException("");
    }
}

2. startViaZygote

private static ProcessStartResult startViaZygote(final String processClass, final String niceName, final int uid, final int gid, final int[] gids, int debugFlags, int mountExternal, int targetSdkVersion, String seInfo, String abi, String instructionSet, String appDataDir, String[] extraArgs) throws ZygoteStartFailedEx {
    synchronized(Process.class) {
        ArrayList<String> argsForZygote = new ArrayList<String>();
        argsForZygote.add("--runtime-args");
        argsForZygote.add("--setuid=" + uid);
        argsForZygote.add("--setgid=" + gid);
        argsForZygote.add("--target-sdk-version=" + targetSdkVersion);
        return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
    }
}

该过程主要工作是生成argsForZygote数组,该数组保存了进程的uid、gid、groups、target-sdk等一系列的参数

3. zygoteSendArgsAndGetResult

首先通过openZygoteSocketIfNeeded(abi)方法是根据当前的abi来选择与zygote还是zygote64来进行通信。

private static ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
    if (primaryZygoteState == null || primaryZygoteState.isClosed()) {
        try {
            //向主zygote发起connect()操作
            primaryZygoteState = ZygoteState.connect(ZYGOTE_SOCKET);
        } catch (IOException ioe) {
            ...
        }
    }

    if (primaryZygoteState.matches(abi)) {
        return primaryZygoteState;
    }

    if (secondaryZygoteState == null || secondaryZygoteState.isClosed()) {
        //当主zygote没能匹配成功,则采用第二个zygote,发起connect()操作
        secondaryZygoteState = ZygoteState.connect(SECONDARY_ZYGOTE_SOCKET);
    }

    if (secondaryZygoteState.matches(abi)) {
        return secondaryZygoteState;
    }
    ...
}

zygoteSendArgsAndGetResult通过socket通道向Zygote进程发送一个参数列表,然后进入阻塞等待状态,直到远端的socket服务端发送回来新创建的进程pid才返回。

private static ProcessStartResult zygoteSendArgsAndGetResult( ZygoteState zygoteState, ArrayList<String> args) throws ZygoteStartFailedEx {
    try {
        final BufferedWriter writer = zygoteState.writer;
        final DataInputStream inputStream = zygoteState.inputStream;
        writer.write(Integer.toString(args.size()));
        writer.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");
            }
            writer.write(arg);
            writer.newLine();
        }

        writer.flush();

        ProcessStartResult result = new ProcessStartResult();
        //等待socket服务端(即zygote)返回新创建的进程pid;
        //对于等待时长问题,Google正在考虑此处是否应该有一个timeout,但目前是没有的。
        result.pid = inputStream.readInt();
        if (result.pid < 0) {
            throw new ZygoteStartFailedEx("fork() failed");
        }
        return result;
    } catch (IOException ex) {
        zygoteState.close();
        throw new ZygoteStartFailedEx(ex);
    }
}

system_server进程的zygoteSendArgsAndGetResult()方法通过socket向Zygote进程发送消息,这是便会唤醒Zygote进程,来响应socket客户端的请求(即system_server端),接下来的操作便是在Zygote来创建进程。

二. Zygote创建进程

简单来说就是Zygote进程是由init进程而创建的,进程启动之后调用ZygoteInit.main()方法,经过创建socket管道,预加载资源后,便进程runSelectLoop()方法。

1. ZygoteInit.main

public static void main(String argv[]) {
    try {
        runSelectLoop(abiList);
    } catch (MethodAndArgsCaller caller) {
        caller.run(); 
    } catch (RuntimeException ex) {
        closeServerSocket();
        throw ex;
    }
}

runSelectLoop()方法会抛出异常MethodAndArgsCaller,从而进入caller.run()方法。

2. runSelectLoop

private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
    ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
    ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
    //sServerSocket是socket通信中的服务端,即zygote进程。保存到fds[0]
    fds.add(sServerSocket.getFileDescriptor());
    peers.add(null);
    while (true) {
        StructPollfd[] pollFds = new StructPollfd[fds.size()];
        for (int i = 0; i < pollFds.length; ++i) {
            pollFds[i] = new StructPollfd();
            pollFds[i].fd = fds.get(i);
            pollFds[i].events = (short) POLLIN;
        }
        try {
             //处理轮询状态,当pollFds有事件到来则往下执行,否则阻塞在这里
            Os.poll(pollFds, -1);
        } catch (ErrnoException ex) {
            ...
        }

        for (int i = pollFds.length - 1; i >= 0; --i) {
            //采用I/O多路复用机制,当接收到客户端发出连接请求 或者数据处理请求到来,则往下执行;
            // 否则进入continue,跳出本次循环。
            if ((pollFds[i].revents & POLLIN) == 0) {
                continue;
            }
            if (i == 0) {
                //即fds[0],代表的是sServerSocket,则意味着有客户端连接请求;
                // 则创建ZygoteConnection对象,并添加到fds。
                ZygoteConnection newPeer = acceptCommandPeer(abiList);
                peers.add(newPeer);
                fds.add(newPeer.getFileDesciptor()); //添加到fds.
            } else {
                //i>0,则代表通过socket接收来自对端的数据,并执行相应操作
                boolean done = peers.get(i).runOnce();
                if (done) {
                    peers.remove(i);
                    fds.remove(i); //处理完则从fds中移除该文件描述符
                }
            }
        }
    }
}

该方法主要功能:

  • 客户端通过openZygoteSocketIfNeeded()来跟zygote进程建立连接。zygote进程收到客户端连接请求后执行accept();然后再创建ZygoteConnection对象,并添加到fds数组列表;
  • 建立连接之后,可以跟客户端通信,进入runOnce()方法来接收客户端数据,并执行进程创建工作。

Android Framwork ---App进程启动(上)

Android Framwork ---App进程启动(中)

Android Framwork ---App进程启动(下)