Framework基礎(chǔ):源于異常的System_Server與受精卵Zygote的共存亡

凌亂.png

System_Server是系統(tǒng)進程,而Zygote是Android java世界的基石。這兩位都在Android中扮演著十分重要的角色。有個很形象的比喻,Zygote是爸爸,System_Server是大兒子,應(yīng)用是一堆小兒子就不說了。今天來說說這兩位仁兄的兩個特性:
1.System_Server使用捕捉異常的方式啟動。
2.Zygote與System_Server共存亡。

System_Server使用捕捉異常的方式啟動

源文件:/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
入口是ZygoteInit的startSystemServer函數(shù),利用forkSystemServer函數(shù)產(chǎn)生了子進程SystemServer,并且設(shè)置了SystemServer的pid,uid,uidgroud等。但這時并沒有進入SystemServer的main函數(shù)入口,只是一個進程跑起來了,懂嗎。

    private static boolean startSystemServer(String abiList, String socketName)
            throws MethodAndArgsCaller, RuntimeException {
        String args[] = {
            "--setuid=1000",   //SystemServer pid=1000,gid=1000,還設(shè)置了權(quán)限組
            "--setgid=1000",
            "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1032,3001,3002,3003,3006,3007",
            "--capabilities=" + capabilities + "," + capabilities,
            "--nice-name=system_server",
            "--runtime-args",
            "com.android.server.SystemServer",    //SystemServer的類名
        };
         ...................
         ...................
         //會利用linux的fork函數(shù)產(chǎn)生SystemServer子進程
            pid = Zygote.forkSystemServer(
                    parsedArgs.uid, parsedArgs.gid,
                    parsedArgs.gids,
                    parsedArgs.debugFlags,
                    null,
                    parsedArgs.permittedCapabilities,
                    parsedArgs.effectiveCapabilities);
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException(ex);
        }

        /* For child process */
        if (pid == 0) {
            if (hasSecondZygote(abiList)) {
                waitForSecondaryZygote(socketName);
            }
            //子進程 SystemServer
            handleSystemServerProcess(parsedArgs);
        }

        return true;
    }


進入handleSystemServerProcess函數(shù),這里的parsedArgs.remainingArgs就是類名com.android.server.SystemServer

    private static void handleSystemServerProcess(
            ZygoteConnection.Arguments parsedArgs)
            throws ZygoteInit.MethodAndArgsCaller {
            ......
            RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
           ..................
        }
    }

/frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
再進入RuntimeInit類的zygoteInit函數(shù)

    public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller {
        commonInit();    //初始化時區(qū)啥的
        nativeZygoteInit();  //native的初始化啥的
        applicationInit(targetSdkVersion, argv, classLoader);  //參數(shù)argv是類名com.android.server.SystemServer
    }

再進入applicationInit函數(shù)

    private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller {
        invokeStaticMain(args.startClass, args.startArgs, classLoader);
    }

再進入invokeStaticMain函數(shù),在這里反射調(diào)用了SystemServer類,并且獲取到main方法,但并沒有執(zhí)行,而是直接拋出一個異常throw new ZygoteInit.MethodAndArgsCaller。

    private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller {
        Class<?> cl;
       cl = Class.forName(className, true, classLoader);//反射獲取SystemServer類
       Method m;
        m = cl.getMethod("main", new Class[] { String[].class });  //獲取main方法
        throw new ZygoteInit.MethodAndArgsCaller(m, argv);   //拋出異常,argv為空
    }

那這個異常是由誰來捕捉呢?其實是在ZygoteInit的main函數(shù)捕捉的,如下圖

異常捕捉.png

異常捕捉后,調(diào)用 caller.run();
這里caller是MethodAndArgsCaller類,是ZygoteInit的內(nèi)部類。run方法會執(zhí)行SystemServer的main方法。從而完成SystemServer的啟動。


    public static class MethodAndArgsCaller extends Exception
            implements Runnable {
        public void run() {
                mMethod.invoke(null, new Object[] { mArgs });
    }
}

為什么SystemServer要采用捕捉異常的方式啟動呢?源碼里面其實有注釋,應(yīng)該是啟動一個新進程時,用來清除之前的堆棧信息的。

Paste_Image.png

Zygote與System_Server共存亡

System_Server是一個很重要的進程,如果掛了,Zygote必須重啟,如果不重啟,手機就會進入假死的狀態(tài),手機黑屏,無聲,無法跟用戶交互等。
Zygote與System_Server共存亡是如何實現(xiàn)的呢?
入口:/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
Zygote調(diào)用forkSystemServer產(chǎn)生子進程SystemServer。

    private static boolean startSystemServer(String abiList, String socketName)
            throws MethodAndArgsCaller, RuntimeException {
            pid = Zygote.forkSystemServer(
                    parsedArgs.uid, parsedArgs.gid,
                    parsedArgs.gids,
                    parsedArgs.debugFlags,
                    null,
                    parsedArgs.permittedCapabilities,
                    parsedArgs.effectiveCapabilities);
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException(ex);
        }
    }

/frameworks/base/core/java/com/android/internal/os/Zygote.java
進入forkSystemServer函數(shù)看看

    public static int forkSystemServer(int uid, int gid, int[] gids, int debugFlags,
            int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
        int pid = nativeForkSystemServer(
                uid, gid, gids, debugFlags, rlimits, permittedCapabilities, effectiveCapabilities);
        return pid;
    }

會jni進入native函數(shù)
/frameworks/base/core/jni/com_android_internal_os_Zygote.cpp

static jint com_android_internal_os_Zygote_nativeForkSystemServer(
        JNIEnv* env, jclass, uid_t uid, gid_t gid, jintArray gids,
        jint debug_flags, jobjectArray rlimits, jlong permittedCapabilities,
        jlong effectiveCapabilities) {
 ............................
  pid_t pid = ForkAndSpecializeCommon(env, uid, gid, gids,
                                      debug_flags, rlimits,
                                      permittedCapabilities, effectiveCapabilities,
                                      MOUNT_EXTERNAL_DEFAULT, NULL, NULL, true, NULL,
                                      NULL, NULL);
 ................................

}

繼續(xù)進入ForkAndSpecializeCommon函數(shù)

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) {
  ...............
...............
  SetSigChldHandler();   //注冊信號,這里將關(guān)系共存亡

  pid_t pid = fork();//fork產(chǎn)生子進程systemserver

  if (pid == 0) {
    .........                //子進程的一些操作
  } else if (pid > 0) {
    // the parent process
  }
  return pid;
}

SetSigChldHandler用于注冊信號,這里就是關(guān)系到Zygote與System_Server的共存亡。

static void SetSigChldHandler() {
  struct sigaction sa;
  memset(&sa, 0, sizeof(sa));
  sa.sa_handler = SigChldHandler;  //信號處理函數(shù)

  int err = sigaction(SIGCHLD, &sa, NULL);   
  if (err < 0) {
    ALOGW("Error setting SIGCHLD handler: %s", strerror(errno));
  }
}

SetSigChldHandler定義了信號處理函數(shù)SigChldHandler,當(dāng)信號SIGCHLD到來的時候,會進入信號處理函數(shù)。
看看信號處理函數(shù)SigChldHandler,可以看到如果子進程SystemServer掛了,Zygote就會自殺。從而完成了共存亡的光輝使命

static void SigChldHandler(int /*signal_number*/) {
  pid_t pid;
  int status;
 //Zygote監(jiān)聽所有子進程的存亡
  while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
 //某一個子進程掛了
 if (WIFSIGNALED(status)) {
      if (WTERMSIG(status) != SIGKILL) {
        ALOGI("Process %d exited due to signal (%d)", pid, WTERMSIG(status));
      }
    }
   //如果掛掉的是SystemServer
    if (pid == gSystemServerPid) {
      ALOGE("Exit zygote because system server (%d) has terminated", pid);
      kill(getpid(), SIGKILL);   //Zygote自殺
    }
  }

}

總結(jié)

1.System_Server采用拋出異常和捕捉異常的方式啟動,可以清除進程的堆棧,減少內(nèi)存占用。
2.System_Server與Zygote共存亡是通過父進程調(diào)用waitpid的方式監(jiān)聽子進程System_Server的死亡,當(dāng)子進程死亡的時候,父進程就自殺

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容