Android 应用程序进程启动

123 阅读4分钟

android 28源码

一 启动Zygote进程

init进程 pid = 1 启动关键服务(ServiceManager、SurfaceFlinger等),守护关键服务

     - 》ServiceManager

     - 》zygote进程

           - 》SystemServer

           - 》 各个app进程

1 native层

/framework/base/cmds/app_process/app_main.cpp 
int main(int argc, char* const argv[]) { 
    ....... 
    if (zygote) { 
        //如果运行在zygote进程中则通过runtim开始启动进程。启动jvm,执行ZygoteInit.main() 
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote); 
    } else if (className) {
        // 其他的更具classname来执行进程。 
        runtime.start("com.android.internal.os.RuntimeInit", args, zygote); 
    } else { 
        fprintf(stderr, "Error: no class name or --zygote supplied.\n"); 
        app_usage();
        LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
    } 
}

2 java层

Zygote启动步骤:

1 加载系统class、资源等(子进程进程共享)

2 准备SocketServer(为启动app进程做准备)

3 启动SystemServer进程

4 等待连接,fork子进程,初始化子进程,进入子进程入口。

ZygoteInit.java 
// 类路径 
private static final String PRELOADED_CLASSES = "/system/etc/preloaded-classes"; 

public static void main(String[] argv) { 
    ....... 
    // 1 预加载资源
    preload(bootTimingsTraceLog);
    ....... 
    // 2 准备SocketServer
    zygoteServer = new ZygoteServer(isPrimaryZygote); 
    ....... 
    if (startSystemServer) { 
        // 3 启动SystemServer进程
        Runnable r = forkSystemServer(abiList, socketName, zygoteServer);
        if (r != null) { 
            // 子进程,也就SystemServer进程,进入SystemServer.main() 
            r.run(); 
            return; 
        } 
    } 
    ....... 
    // Zygote进程等待连接 4 等待连接,fork子进程,初始化子进程,进入子进程入口。
    caller = zygoteServer.runSelectLoop(abiList);
} 

static void preload(TimingsTraceLog bootTimingsTraceLog) {
    ...... 
    bootTimingsTraceLog.traceBegin("PreloadClasses"); 
    preloadClasses(); // 加载系统class 
    ....... 
    bootTimingsTraceLog.traceBegin("PreloadResources");
    preloadResources(); // 加载资源 
    bootTimingsTraceLog.traceEnd(); 
    ....... 
    preloadSharedLibraries(); 
    preloadTextResources(); 
} 

// 预加载资源 
private static void preloadClasses() { 
    InputStream is; 
    try { 
        is = new FileInputStream(PRELOADED_CLASSES);
    } catch (FileNotFoundException e) {
        Log.e(TAG, "Couldn't find " + PRELOADED_CLASSES + "."); 
        return; 
    }
    ...... 
    Class.forName(line, true, null); // 加载类 
    ....... 
} 

// 3 启动SystemServer进程 
private static Runnable forkSystemServer(String abiList, String socketName, ZygoteServer zygoteServer) {
    ...... 
    // 启动SystemServer 
    pid = Zygote.forkSystemServer( parsedArgs.mUid, parsedArgs.mGid, parsedArgs.mGids, parsedArgs.mRuntimeFlags, null, parsedArgs.mPermittedCapabilities, parsedArgs.mEffectiveCapabilities); 
    ...... 
    /* For child process */ 
    if (pid == 0) { 
        // 子进程,也就是SystemServer进程
        if (hasSecondZygote(abiList)) {
            waitForSecondaryZygote(socketName);
        } 
        zygoteServer.closeServerSocket(); 
        // 进程入口:调用SystemServer.main()
        return handleSystemServerProcess(parsedArgs); 
    } 
}

二 App进程启动

ActivityManagerService会通过调用startProcessLocked函数来向Zygote进程发送请求,主要流程如下:

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java 
startProcessLocked() // final String entryPoint = "android.app.ActivityThread" 进程入口 
startProcess() 

frameworks/base/core/java/android/os/Process.java 
start() 
startViaZygote() // 拼接启动参数,包括entryPoint = "android.app.ActivityThread" 
openZygoteSocketIfNeeded() // 连接Zygote socket 
zygoteSendArgsAndGetResult() // 通过socket与Zygote进程通信,把启动参数传给Zygote进程 

frameworks/base/core/java/com/android/internal/os/ZygoteInit.java 
runSelectLoop() // zygote进程启动后,一直在runSelectLoop中等待client连接 

frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java 
processOneCommand() // fork子进程, 子进程返回Runnable对象。父进程返回null 
     Zygote.forkAndSpecialize() fork子进程 
handleChildProc() // 子进程处理, 
    ZygoteInit.zygoteInit() //子进程初始化

frameworks/base/core/java/com/android/internal/os/ZygoteInit.java 
main() // 子进程关闭socket,根据runSelectLoop返回的caller,调用android.app.ActivityThread.main()

ActivityManagerService调用Process.start()启动进程。

ActivityManagerService.java 
private boolean startProcessLocked(String hostingType, 
    String hostingNameStr, String entryPoint, ProcessRecord app, 
    int uid, int[] gids, int runtimeFlags, int mountExternal, 
    String seInfo, String requiredAbi, String instructionSet, 
    String invokeWith, long startTime) {
    ........ 
    final ProcessStartResult startResult = startProcess(app.hostingType, 
    entryPoint, app, app.startUid, gids, runtimeFlags, mountExternal, 
    app.seInfo, requiredAbi, instructionSet, invokeWith, app.startTime); 
    ........ 
} 

private ProcessStartResult startProcess(String hostingType, 
    String entryPoint, ProcessRecord app, int uid, int[] gids, i
    nt runtimeFlags, int mountExternal, String seInfo, 
    String requiredAbi, String instructionSet, String invokeWith, 
    long startTime) { 
    if (hostingType.equals("webview_service")) { 
        startResult = startWebView(entryPoint, app.processName, uid, uid, gids, runtimeFlags, mountExternal, app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet, app.info.dataDir, null, new String[] {PROC_START_SEQ_IDENT + app.startSeq}); 
    } else { 
        startResult = Process.start(entryPoint, app.processName, uid, uid, gids, runtimeFlags, mountExternal, app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet, app.info.dataDir, invokeWith, new String[] {PROC_START_SEQ_IDENT + app.startSeq});
    } 
}

android.os.Process.java 
public static final ProcessStartResult start(final String processClass,
    final String niceName, int uid, int gid, int[] gids, int runtimeFlags, 
    int mountExternal, int targetSdkVersion, String seInfo, String abi, 
    String instructionSet, String appDataDir, String invokeWith, 
    String[] zygoteArgs) { 
    return zygoteProcess.start(processClass, niceName, uid, gid, gids, 
    runtimeFlags, mountExternal, targetSdkVersion, seInfo, abi, 
    instructionSet, appDataDir, invokeWith, zygoteArgs); 
 }

ZygoteProcess:负责建立连接,拼接数据,传输数据

ZygoteProcess.java 
private Process.ProcessStartResult startViaZygote(final String processClass, final String niceName, final int uid, final int gid, final int[] gids, int runtimeFlags, int mountExternal, int targetSdkVersion, String seInfo, String abi, String instructionSet, String appDataDir, String invokeWith, boolean startChildZygote, String[] extraArgs) throws ZygoteStartFailedEx {
    ...... 
    // 拼接启动参数 
    synchronized(mLock) {
        // openZygoteSocketIfNeeded() 建立连接, 
        // zygoteSendArgsAndGetResult() 使用连接,传输参数。 
        return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
    } 
}

ZygoteInit:等待连接,创建ZygoteConnection对象(处理连接)。

frameworks/base/core/java/com/android/internal/os/ZygoteInit.java 
Runnable runSelectLoop(String abiList) { 
    ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>(); 
    ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>(); 
    // Server端fd保存在第0个 
    fds.add(mServerSocket.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 { 
            // POLL监听,server端有连接或者client端有输入都会唤醒。 
            Os.poll(pollFds, -1); 
        } catch (ErrnoException ex) { 
            throw new RuntimeException("poll failed", ex);
        } 
        for (int i = pollFds.length - 1; i >= 0; --i) { 
            // 轮询,有可读事件才处理; 
            if ((pollFds[i].revents & POLLIN) == 0) {
                continue; 
            } 
            if (i == 0) { 
                // 1 第0个是Server的fd,有连接请求 
                ZygoteConnection newPeer = acceptCommandPeer(abiList); 
                // 把连接加入数组,下一次for循环使用 
                peers.add(newPeer); 
                fds.add(newPeer.getFileDesciptor()); 
            } else { 
                try { 
                    // 取出{1处}连接 
                    ZygoteConnection connection = peers.get(i); 
                    final Runnable command = connection.processOneCommand(this); 
                    if (mIsForkChild) { 
                        ....... 
                        // 子线程返回Runnable command 
                        return command; 
                    } else { 
                        ....... 
                    } 
                } catch (Exception e) { 
                    ....... 
               }    
            }
        }
    }
} 
                    
// app进程初始化 
public static final Runnable zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) { 
    if (RuntimeInit.DEBUG) { 
        Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote"); 
    } 
    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit"); 
    RuntimeInit.redirectLogStreams(); 
    
    // 设置setDefaultUncaughtExceptionHandler、setUncaughtExceptionPreHandler 
    RuntimeInit.commonInit(); 
    // frameworks/base/core/jni/AndroidRuntime.cpp 创建Binder线程池 
    ZygoteInit.nativeZygoteInit(); 
    // 设置堆,设置targetSdkVersion
    // 找到main方法(android.app.ActivityThread.main()),封装成MethodAndArgsCaller,在ZygoteInit.main()中执行 
    return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
}

ZygoteConnection:处理一次连接,fork子进程,通过ZygoteInit.zygoteInit()初始化子进程

ZygoteConnection.java 
private final LocalSocket mSocket; 
private final DataOutputStream mSocketOutStream; 
private final BufferedReader mSocketReader; 

ZygoteConnection(LocalSocket socket, String abiList) throws IOException { 
    mSocket = socket; 
    this.abiList = abiList; 
    mSocketOutStream = new DataOutputStream(socket.getOutputStream()); 
    mSocketReader = new BufferedReader( new InputStreamReader(socket.getInputStream()), 256);
    mSocket.setSoTimeout(CONNECTION_TIMEOUT_MILLIS); 
    try { 
        peer = mSocket.getPeerCredentials(); 
    } catch (IOException ex) { 
        Log.e(TAG, "Cannot read peer credentials", ex);
        throw ex; 
    }
    isEof = false; 
} 

Runnable processOneCommand(ZygoteServer zygoteServer) { 
    String args[]; 
    Arguments parsedArgs = null; 
    FileDescriptor[] descriptors; 
    try { 
        // 从连接中读取数据 
        args = readArgumentList(); 
        descriptors = mSocket.getAncillaryFileDescriptors(); 
     } catch (IOException ex) { 
         throw new IllegalStateException("IOException on command socket", ex); 
     }
     ....... 
     pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, 
         parsedArgs.gids, parsedArgs.runtimeFlags, rlimits, 
         parsedArgs.mountExternal, parsedArgs.seInfo, 
         parsedArgs.niceName, fdsToClose, fdsToIgnore, 
         parsedArgs.startChildZygote, parsedArgs.instructionSet, 
         parsedArgs.appDataDir); 
     try { 
         if (pid == 0) { 
             // 子线程 zygoteServer.setForkChild(); 
             zygoteServer.closeServerSocket(); 
             IoUtils.closeQuietly(serverPipeFd); 
             serverPipeFd = null; 
             // 通过参数,初始化进程。返回Runnable,直接调用android.app.ActivityThread.main() 
             return handleChildProc(parsedArgs, descriptors, childPipeFd, parsedArgs.startChildZygote); 
         } else { 
             // In the parent. A pid < 0 indicates a failure and will be handled in 
             // handleParentProc. 
             IoUtils.closeQuietly(childPipeFd); 
             childPipeFd = null; 
             handleParentProc(pid, descriptors, serverPipeFd);
             return null; 
         } 
     } finally { 
         IoUtils.closeQuietly(childPipeFd); 
         IoUtils.closeQuietly(serverPipeFd);
     }
} 

private Runnable handleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors, FileDescriptor pipeFd, boolean isZygote) {
    // 数据已传输完成,关闭连接 
    closeSocket(); 
    ....... 
    if (parsedArgs.invokeWith != null) { 
        ..... 
    } else { 
        if (!isZygote) { 
            // app 进程。初始化进程 
            return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, null /* classLoader */); 
        } else { 
            return ZygoteInit.childZygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, null /* classLoader */);
        } 
    }
}

MethodAndArgsCaller:app进程入口封装。

RuntimeInit.java 

static class MethodAndArgsCaller 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 }); 
        } 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); 
        } 
    } 
   
   
}