Android 四大組件 - 進程的 fork 創建過程

相關文章鏈接:

1. Android Framework - 學習啓動篇
2. Android 系統服務 - AMS 的啓動過程
3. Android 系統服務 - PMS 的啓動過程
4. Android Framework - 開機啓動 Zygote 進程

相關源碼文件:

/frameworks/base/services/core/java/android/os/Process.java
/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
/frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
/frameworks/base/core/java/com/android/internal/os/Zygote.java
/frameworks/base/core/jni/com_android_internal_os_Zygote.cpp
/frameworks/base/core/java/android/app/ActivityThread.java
/frameworks/base/core/java/android/app/LoadedApk.java

1. AMS 與 Zygote 通信過程

無論是點擊桌面圖標調用 startActivitySafely 還是直接調用 startActivity 在源碼中都是調用的 startActivityForResult 方法。由於 Activity 的啓動流程有些複雜,因此本文先從進程的 fork 創建過程來入手分析。

    void startSpecificActivityLocked(ActivityRecord r,
            boolean andResume, boolean checkConfig) {
        // Is this activity's process already running?
        ProcessRecord app = mService.getProcessRecordLocked(r.processName,
                r.info.applicationInfo.uid, true);

        r.task.stack.setLaunchTime(r);
        // 判斷進程是否創建
        if (app != null && app.thread != null) {
          ...
        }
        // 當前進程沒有創建則先創建進程
        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                "activity", r.intent.getComponent(), false, false, true);
    }

    private final void startProcessLocked(ProcessRecord app, String hostingType,
            String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
        try {
            // 設置參數
            ...
            // 設置 entryPoint = "android.app.ActivityThread"
            boolean isActivityProcess = (entryPoint == null);
            if (entryPoint == null) entryPoint = "android.app.ActivityThread";
            // 啓動創建進程
            Process.ProcessStartResult startResult = Process.start(entryPoint,
                    app.processName, uid, uid, gids, debugFlags, mountExternal,
                    app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
                    app.info.dataDir, entryPointArgs);
           
            synchronized (mPidsSelfLocked) {
                // 緩存 pid 和 進程信息
                this.mPidsSelfLocked.put(startResult.pid, app);
                ...
            }
            ...
        } catch (RuntimeException e) {
            ...
        }
    }

    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);
            ...
            // 向 zygote 發起創建進程的請求,通過 socket 的方式
            return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
        }
    }

    // 打開 zygot socket 連接
    private static ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
        if (primaryZygoteState == null || primaryZygoteState.isClosed()) {
            try {
                primaryZygoteState = ZygoteState.connect(ZYGOTE_SOCKET);
            } 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);
            } 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);
    }

    private static ProcessStartResult zygoteSendArgsAndGetResult(
            ZygoteState zygoteState, ArrayList<String> args)
            throws ZygoteStartFailedEx {
        try {
            // 獲取 socket 的 output 與 input
            final BufferedWriter writer = zygoteState.writer;
            final DataInputStream inputStream = zygoteState.inputStream;
            // 把數據傳送給 zygote 進程
            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();

            // 處理 zygote fork 進程返回的結果
            ProcessStartResult result = new ProcessStartResult();
            result.pid = inputStream.readInt();
            if (result.pid < 0) {
                throw new ZygoteStartFailedEx("fork() failed");
            }
            result.usingWrapper = inputStream.readBoolean();
            return result;
        } catch (IOException ex) {
            // 有異常則關閉連接
            zygoteState.close();
            throw new ZygoteStartFailedEx(ex);
        }
    }

activity 的啓動過程中會掉用 startSpecificActivityLocked 方法,首先會根據 processName 和 uid 來判斷進程是否有創建,如果沒有創建進程則需要先創建進程,processName 默認情況是包名,uid 是由 PMS 在啓動的過程中解析計算好的,其具體的計算賦值過程可以參考《Android 系統服務 - PMS 的啓動過程》

如果當前進程沒有創建,則調用 Process 的 startViaZygote 方法去創建進程,就是向 Zygote 進程發起創建進程的請求,這裏跨進程通信採用的是 Socket 套接字的方式。注意,其中有一個重要的參數 entryPoint 是 android.app.ActivityThread 。

2. Zygote fork 創建進程

    // 循環讀取處理請求
    private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
        ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
        ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();

        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 {
                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) {
                    ZygoteConnection newPeer = acceptCommandPeer(abiList);
                    peers.add(newPeer);
                    fds.add(newPeer.getFileDesciptor());
                } else {
                    boolean done = peers.get(i).runOnce();
                    if (done) {
                        peers.remove(i);
                        fds.remove(i);
                    }
                }
            }
        }
    }

    boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
        try {
            // 讀取 AMS 發過來的參數
            args = readArgumentList();
        } catch (IOException ex) {
            ...
            return true;
        }
       
        try {
            parsedArgs = new Arguments(args);

            // fork 創建進程
            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 {
            if (pid == 0) {
                // child process 處理
                handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
                return true;
            } else {
                // parent process 處理
                return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);
            }
        } finally {
            IoUtils.closeQuietly(childPipeFd);
            IoUtils.closeQuietly(serverPipeFd);
        }
    }

    public static int forkAndSpecialize(int uid, int gid, int[] gids, int debugFlags,
          int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
          String instructionSet, String appDataDir) {
        int pid = nativeForkAndSpecialize(
                  uid, gid, gids, debugFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
                  instructionSet, appDataDir);
        ...
        return pid;
    }

    static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGids,
                                     jint debug_flags, jobjectArray javaRlimits,
                                     jlong permittedCapabilities, jlong effectiveCapabilities,
                                     jint mount_external,
                                     jstring java_se_info, jstring java_se_name,
                                     bool is_system_server, jintArray fdsToClose,
                                     jstring instructionSet, jstring dataDir) {
      // 調用系統函數 fork
      pid_t pid = fork();
      ...
      return pid;
    }

    private void handleChildProc(Arguments parsedArgs,
            FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)
            throws ZygoteInit.MethodAndArgsCaller {
        // 關閉 zygote 進程繼承過來的 socket 連接
        closeSocket();
        ZygoteInit.closeServerSocket();
        ...
        if (parsedArgs.invokeWith != null) {
            ...
        } else {
            RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,
                    parsedArgs.remainingArgs, null /* classLoader */);
        }
    }

    public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller {
        // common 初始化
        commonInit();
        // 初始化打開 binder 驅動
        nativeZygoteInit();
        // 拋異常,然後執行 ActivityThread.main 方法
        applicationInit(targetSdkVersion, argv, classLoader);
    }

Zygote 啓動後會循環處理客戶端發過來的請求,當接收到請求後會調用 ZygoteConnection 的 runOnce 方法,解析到客戶端的參數後會調用 native 底層的 fork 的方法,至此進程才真正創建完畢。進程 fork 完畢後,Zygote 進程會將信息返回給 AMS,新創建的進程會調用 commonInit 、nativeZygoteInit 和 applicationInit 三個核心方法:

  • commonInit:通用初始化方法
  • nativeZygoteInit:打開底層 binder 驅動
  • applicationInit:調用 ActivityThread 的 main 方法

3. Application 的創建與綁定

    public static void main(String[] args) {
        // 創建主線程 Looper 
        Looper.prepareMainLooper();

        ActivityThread thread = new ActivityThread();
        thread.attach(false);

        // 進入 loop 循環
        Looper.loop();
    }

    private void attach(boolean system) {
        if (!system) {
            final IActivityManager mgr = ActivityManagerNative.getDefault();
            try {
                // 像 AMS 發起綁定請求
                mgr.attachApplication(mAppThread);
            } catch (RemoteException ex) {
                // Ignore
            }
            ...
        } else {
           ...
        }
    }

    public final void attachApplication(IApplicationThread thread) {
        synchronized (this) {
            int callingPid = Binder.getCallingPid();
            final long origId = Binder.clearCallingIdentity();
            attachApplicationLocked(thread, callingPid);
            Binder.restoreCallingIdentity(origId);
        }
    }

    private final boolean attachApplicationLocked(IApplicationThread thread,
            int pid) {
        // 通過 pid 查詢到進程信息,之前 fork 後有緩存
        ProcessRecord app;
        if (pid != MY_PID && pid >= 0) {
            synchronized (mPidsSelfLocked) {
                app = mPidsSelfLocked.get(pid);
            }
        } else {
            app = null;
        }
        ...
        // 綁定 thread
        app.makeActive(thread, mProcessStats);
        ...
        try {
            // 回調 bindApplication 方法
            thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,
                    profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,
                    app.instrumentationUiAutomationConnection, testMode, enableOpenGlTrace,
                    isRestrictedBackupMode || !normalMode, app.persistent,
                    new Configuration(mConfiguration), app.compat,
                    getCommonServicesLocked(app.isolated),
                    mCoreSettingsObserver.getCoreSettingsLocked());
        } catch (Exception e) {
            ...
            return false;
        }
        return true;
    }

    private void handleBindApplication(AppBindData data) {
        try {
            // 創建綁定 Application
            Application app = data.info.makeApplication(data.restrictedBackupMode, null);
            mInitialApplication = app;    
        } finally {
            StrictMode.setThreadPolicy(savedPolicy);
        }
    }

    public Application makeApplication(boolean forceDefaultAppClass,
            Instrumentation instrumentation) {
        if (mApplication != null) {
            return mApplication;
        }

        Application app = null;
        // 查找到 application 的 class 
        String appClass = mApplicationInfo.className;
        if (forceDefaultAppClass || (appClass == null)) {
            // 默認是 android.app.Application
            appClass = "android.app.Application";
        }

        try {
            // 先創建 ClassLoader
            java.lang.ClassLoader cl = getClassLoader();
            if (!mPackageName.equals("android")) {
                initializeJavaContextClassLoader();
            }
            // 創建一個 ContextImpl 
            ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
            // 創建和綁定 Application
            app = mActivityThread.mInstrumentation.newApplication(
                    cl, appClass, appContext);
            appContext.setOuterContext(app);
        } catch (Exception e) {
            if (!mActivityThread.mInstrumentation.onException(app, e)) {
                throw new RuntimeException(
                    "Unable to instantiate application " + appClass
                    + ": " + e.toString(), e);
            }
        }
        mActivityThread.mAllApplications.add(app);
        mApplication = app;
        if (instrumentation != null) {
            try {
                // 調用 Application 的 onCreate 方法
                instrumentation.callApplicationOnCreate(app);
            } catch (Exception e) {
                if (!instrumentation.onException(app, e)) {
                    throw new RuntimeException(
                        "Unable to create application " + app.getClass().getName()
                        + ": " + e.toString(), e);
                }
            }
        }
        ...
        return app;
    }
    // 創建 application 並且調用 attach 方法
    static public Application newApplication(Class<?> clazz, Context context)
            throws InstantiationException, IllegalAccessException, 
            ClassNotFoundException {
        Application app = (Application)clazz.newInstance();
        app.attach(context);
        return app;
    }

進程 fork 後會執行 ActivityThread 的 main 方法,該方法又會向 AMS 發起綁定 IApplicationThread 請求,這裏 IApplicationThread 是一個可以跨進程通信的 Binder 對象,然後 AMS 又會調用 IApplicationThread 的 bindApplication 方法去創建應用的 Application,等應用的 Application 創建完畢後,纔會真正的開始創建啓動 Activity 。

視頻地址:https://pan.baidu.com/s/1tB9hDc_6Aw_L0pgtbAU8Sw
視頻密碼:6fzw

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章