Android源碼分析--system_server進程分析

來源:互聯網
上載者:User

標籤:android   源碼   系統   

在上一篇博文中我們進行了有關Zygote進程的分析,我們知道Zygote進程建立了一個重要的進程–system_server進程後就進入了無限迴圈中,之後Android系統中的重要任務就交給了system_server進程,作為zygote的嫡長子進程,system_server進程的意義非凡,今天我們來分析一下system_server進程。

建立system_server進程

在ZygoteInit中main方法中,通過調用startSystemServer方法開啟了system_server進程。該方法主要為建立system_server進程準備了一些參數,並調用本地方法forkSystemServer建立system_server進程。讓我們來看一下startSystemServer方法的代碼:

    private static boolean startSystemServer()            throws MethodAndArgsCaller, RuntimeException {        String args[] = {            "--setuid=1000",            "--setgid=1000",            "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1032,3001,3002,3003,3006,3007",            "--capabilities=130104352,130104352",            "--runtime-init",            "--nice-name=system_server",            "com.android.server.SystemServer",        };        ZygoteConnection.Arguments parsedArgs = null;        int pid;        try {            parsedArgs = new ZygoteConnection.Arguments(args);            ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);            ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);            /* 建立system_server進程 */            pid = Zygote.forkSystemServer(                    parsedArgs.uid, parsedArgs.gid,                    parsedArgs.gids,                    parsedArgs.debugFlags,                    null,                    parsedArgs.permittedCapabilities,                    parsedArgs.effectiveCapabilities);        } catch (IllegalArgumentException ex) {            throw new RuntimeException(ex);        }        /* 子進程中執行 */        if (pid == 0) {            handleSystemServerProcess(parsedArgs);        }        return true;    }

這裡的代碼並不複雜,可以看到,他調用了forkSystemServer方法來建立一個新的進程,之後在子進程,即system_server進程中執行handleSystemServerProcess方法。下面我們來看一下forkSystemServer方法,它是一個native方法對應的源檔案在dalvik\vm\native\dalvik_system_Zygote.cpp中。代碼如下:

static void Dalvik_dalvik_system_Zygote_forkSystemServer(        const u4* args, JValue* pResult){    pid_t pid;    pid = forkAndSpecializeCommon(args, true);    /* zygote進程檢查其子進程是否死掉 */    if (pid > 0) {        int status;        ALOGI("System server process %d has been created", pid);        gDvm.systemServerPid = pid;        /*  如果system_server進程退出,則zygote進程也會被殺掉 */        if (waitpid(pid, &status, WNOHANG) == pid) {            ALOGE("System server process %d has died. Restarting Zygote!", pid);            kill(getpid(), SIGKILL);        }    }    RETURN_INT(pid);}

從代碼中可以看到在forkAndSpecializeCommon方法中,我們建立了子進程,並返回了子進程id,接下來我檢查如果system_server進程是否退出,若是的話則zygote進程也將會被被幹掉,由此可見其重要性。接下來我們來看forkAndSpecializeCommon的代碼,這個system_server進程的建立真的是千峰百轉啊。。。

static pid_t forkAndSpecializeCommon(const u4* args, bool isSystemServer){    pid_t pid;    uid_t uid = (uid_t) args[0];    gid_t gid = (gid_t) args[1];    ArrayObject* gids = (ArrayObject *)args[2];    u4 debugFlags = args[3];    ArrayObject *rlimits = (ArrayObject *)args[4];    u4 mountMode = MOUNT_EXTERNAL_NONE;    int64_t permittedCapabilities, effectiveCapabilities;    char *seInfo = NULL;    char *niceName = NULL;    //傳入參數isSystemServer為true    if (isSystemServer) {        permittedCapabilities = args[5] | (int64_t) args[6] << 32;        effectiveCapabilities = args[7] | (int64_t) args[8] << 32;    } else {       ......    }    if (!gDvm.zygote) {        dvmThrowIllegalStateException(            "VM instance not started with -Xzygote");        return -1;    }    // 在第一次調用fork函數之前需要調用    if (!dvmGcPreZygoteFork()) {        ALOGE("pre-fork heap failed");        dvmAbort();    }    setSignalHandler();    //向log檔案中寫入一些資料    dvmDumpLoaderStats("zygote");    //子進程被fork出來    pid = fork();    if (pid == 0) {    //在這雷根據傳入的參數對子進程做出一些處理,例如設定進程名,設定各種id等    ......    }    return pid;}

至此system_server進程終於被建立出來,我們可以看到system_server進程也是通過Linux系統特有的Fork機制分裂複製出來的。在fork之前,我們還有一個重要方法沒有分析–setSignalHandler方法,該方法用來設定訊號處理,下面讓我來看一下吧。

static void setSignalHandler(){    int err;    struct sigaction sa;    memset(&sa, 0, sizeof(sa));    sa.sa_handler = sigchldHandler;    err = sigaction (SIGCHLD, &sa, NULL);//設定訊號處理函數,該訊號是子進程死亡的訊號    if (err < 0) {        ALOGW("Error setting SIGCHLD handler: %s", strerror(errno));    }}static void sigchldHandler(int s){    pid_t pid;    int status;    while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {        /* 列印出我們所關心的進程的死亡狀態. */        ......        /*         * 如果剛剛銷毀的進程是system_server, 同時殺死zygote進程         * 這樣system_server進程和zygote進程將會被init進程重啟         */        if (pid == gDvm.systemServerPid) {            ALOG(LOG_INFO, ZYGOTE_LOG_TAG,                "Exit zygote because system server (%d) has terminated",                (int) pid);            kill(getpid(), SIGKILL);        }    }    if (pid < 0) {        ALOG(LOG_WARN, ZYGOTE_LOG_TAG,            "Zygote SIGCHLD error in waitpid: %s",strerror(errno));    }}

這裡我們發現我們之前已經看到在forkSystemServer方法中已經檢查過system_server進程是否死亡,為什麼這裡還要再一次進行檢查?這是為了防止在我們還沒有得到fork子進程的pid時,system_server進程就已經死亡的情況。

總結一下:system_server進程的建立經曆了漫長的曆程:首先startSystemServer中調用了native方法forkSystemServer;之後在native方法forkSystemServer中調用了forkAndSpecializeCommon方法;在forkAndSpecializeCommon方法中fork之前還調用了setSignalHandler來設定訊號處理項。這樣,我們的system_server進程終於被建立起來,同時他還和zygote進程保持著同生共死的關係。

system_server進程的職責

在startSystemServer的方法中我們可以看到,在建立進程之後,在子進程即system_server進程中會執行handleSystemServerProcess方法,這便是system_server的職責所在,下面我們來看一下:

    private static void handleSystemServerProcess(            ZygoteConnection.Arguments parsedArgs)            throws ZygoteInit.MethodAndArgsCaller {        closeServerSocket();        // 設定許可權.        Libcore.os.umask(S_IRWXG | S_IRWXO);        ......        if (parsedArgs.invokeWith != null) {        ......        } else {            /* 剩餘的參數傳遞到SystemServer. */            RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs);        }    }

可以看到最後system_server進程來到了RuntimeInit中,它的實現在frameworks\base\core\java\com\android\internal\os\RuntimeInit.java中

    public static final void zygoteInit(int targetSdkVersion, String[] argv)            throws ZygoteInit.MethodAndArgsCaller {        if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");        //關閉System.out和System.err,使用Android log        redirectLogStreams();        //做一些常規初始化        commonInit();        //native層初始化,調用此方法之後system_server將與Binder通訊系統建立聯絡,這樣就可以使用Binder了        nativeZygoteInit();        applicationInit(targetSdkVersion, argv);    }    private static void applicationInit(int targetSdkVersion, String[] argv)            throws ZygoteInit.MethodAndArgsCaller {        ......        try {            args = new Arguments(argv);        } catch (IllegalArgumentException ex) {            Slog.e(TAG, ex.getMessage());            // let the process exit            return;        }        invokeStaticMain(args.startClass, args.startArgs);    }

可以看到,最終我們調用了invokeStaticMain方法,該方法的傳入參數在startSystemServer方法中被設定,其傳入參數的類名是”com.android.server.SystemServer”

    private static void invokeStaticMain(String className, String[] argv)            throws ZygoteInit.MethodAndArgsCaller {        Class<?> cl;        try {            cl = Class.forName(className);        } catch (ClassNotFoundException ex) {            throw new RuntimeException(                    "Missing class when invoking static main " + className,                    ex);        }        Method m;        try {            m = cl.getMethod("main", new Class[] { String[].class });        } catch (NoSuchMethodException ex) {            throw new RuntimeException(                    "Missing static main on " + className, ex);        } catch (SecurityException ex) {            throw new RuntimeException(                    "Problem getting static main on " + className, ex);        }        int modifiers = m.getModifiers();        if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {            throw new RuntimeException(                    "Main method is not public and static on " + className);        }        /* 拋出的異常在ZygoteInit.main()中被截獲 */        throw new ZygoteInit.MethodAndArgsCaller(m, argv);    }

讓我們來看看被截獲的語句:

 catch (MethodAndArgsCaller caller) {            caller.run();//調用了caller的run方法        } 

run方法代碼:

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);            }        }

可以看到,在函數最後拋出異常,在ZygoteInit.main()中被截獲,由於傳遞的參數類名是”com.android.server.SystemServer”,這樣我們調用了MethodAndArgsCaller.run()方法去執行了SystemServer類的靜態main方法。(關於ZygoteInit可以參考上一篇博文:Android源碼分析–Zygote進程分析)

    public static void main(String[] args) {        ......        // Mmmmmm... more memory!        dalvik.system.VMRuntime.getRuntime().clearGrowthLimit();        // system server一直在運行, 所以他需要儘可能有效利用記憶體        VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);        Environment.setUserRequired(true);        System.loadLibrary("android_servers");        Slog.i(TAG, "Entered the Android system server!");        // native方法,進行一些感應器服務的初始化        nativeInit();        // 建立一個單獨的線程,在這裡啟動系統的各項服務        ServerThread thr = new ServerThread();        thr.initAndLoop();    }

最終,system_server開啟了一個新的線程,並執行了它的initAndLoop方法,其也被定義在SystemServer.java中,該方法的代碼較多,其主要的工作就是開啟了系統中的各項服務,如電池服務,藍芽服務等等。並調用了Looper的prepareMainLooper方法進行訊息迴圈,然後處理訊息,這裡不再贅述。

最後,我們來總結一下:

  • 首先system_server執行handleSystemServerProcess方法來完成自己的使命;
  • 之後調用RuntimeInit.zygoteInit方法,在這裡我們進行了一些常規的初始化工作已經native層的初始化,從而與Binder通訊建立聯絡;
  • 之後調用invokeStaticMain方法,利用拋出異常的方法在ZygoteInit的main方法中截獲並去執行SystemServer的main方法;
  • 在SystemServer的main方法中,我調用nativeInit方法去初始化一些感應器服務,並開啟了單獨的線程去開啟Android系統中的各項服務,並調用了Looper的prepareMainLooper方法進行訊息迴圈,然後處理訊息

Android源碼分析--system_server進程分析

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.