【Android源碼分析】Android系統關鍵服務啓動簡析

一、關於Android系統重要的進程

(1)、init進程:init進程是Linux內核啓動完成之後,啓動的第一個用戶進程,Android系統就是在這個進程的基礎上啓動起來的,進程pid爲1。init進程通過解析init.rc來陸續啓動其他關鍵的系統服務進程---其中最重要的是:ServiceManagerZygoteSystemServer

(2)、ServiceManager:主要負責添加服務,獲取服務,查找服務以及當某個服務意外終止時,對該服務的資源進行回收。
(3)、Zygote進程:Zygote是一個孵化器進程,所有的應用程序進程以及系統服務進程SystemServer都是由Zygote進程fork出來的。在Zygote中進行添加虛擬機參數,並將其啓動起來,然後註冊JNI函數。在Zygote中進行預加載以及初始化核心類庫。最後將SystemServer啓動起來。
(4)、SystemServer:啓動系統各項服務。

二、init.rc腳本語法規則

service <name> <pathname> [ <argument> ]*   //service的名字,啓動路徑,以及參數
   <option>      
   <option>
    ...

<name>:
表示此service的名稱
<pathname>:
此service所在的路徑。因爲是可執行文件,所以一定有存儲路徑。
<argument>:
啓動service所帶的參數。
<option>:
對此service的約束選項。

三、ServiceManager,Zygote,SystemServer的啓動簡析

3.1 ServiceManager

       ServiceManager是Binder機制中的“DNS服務器”,負責域名(某Binder服務在ServiceManager註冊時提供的名稱)IP地址(由底層Binder驅動分配的值)的解析。
       ServiceManager是在servicemanager.rc(Android8.0)裏面描述,並由init進程啓動。

/*android-8.0.0_r1\frameworks\native\cmds\servicemanager\servicemanager.rc*/
service servicemanager /system/bin/servicemanager
    class core animation
    user system
    group system readproc
    critical
    onrestart restart healthd
    onrestart restart zygote
    onrestart restart audioserver
    onrestart restart media
    onrestart restart surfaceflinger
    onrestart restart inputflinger
    onrestart restart drm
    onrestart restart cameraserver
    writepid /dev/cpuset/system-background/tasks

       可以看到,Servicemanager是一個Linux程序。它在設備中的存儲路徑是:/system/bin/servicemanager,源碼路徑則是:
android-8.0.0_r1\frameworks\native\cmds\servicemanager\servicemanager.c

 

      ServiceManager所屬的classcore,其他同類的系統進程包括ueventd,console(/system/bin/sh),adbd等。根據core組的特性,這些進程會同時被啓動或停止。另外,critical選項說明它是系統的關鍵進程---意味着如果進程不幸在4分鐘內異常退出超過4次,則設備將重啓並進入還原模式。當ServiceManager每次重啓是,其他關鍵進程如zygote,media,surfaceflinger等也會被restart。

3.2 Zygote

       在Android系統中,所有的應用程序進程以及系統服務進程SystemServer都是由Zygote進程孕育(fork)出來的,因爲Android系統是基於Linux內核的,而在Linux系統中,所有的進程都是init進程的子孫進程,也就是說,所有的進程都是直接或者間接地由init進程fork出來的。Zygote進程也不例外,它是在系統啓動的過程,由init進程創建的,在系統啓動腳本android-8.0.0_r1\system\core\rootdir\init.*.rc文件中,我們可以看到啓動Zygote進程的腳本命令:

/*android-8.0.0_r1\system\core\rootdir\init.*.rc*/例如:init.zygote32.rc
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
    class main
    priority -20
    user root
    group root readproc
    socket zygote stream 660 root system
    onrestart write /sys/android_power/request_state wake
    onrestart write /sys/power/state on
    onrestart restart audioserver
    onrestart restart cameraserver
    onrestart restart media
    onrestart restart netd
    onrestart restart wificond
    writepid /dev/cpuset/foreground/tasks


從上面這段腳本描述可以看出:
ServiceName:zygote
Path:/system/bin/app_process
Arguments:-Xzygote /system/bin --zygote --start-system-server

       Zygote所屬classmain,而不是core。和其同class的系統進程有netd,debuggerd,rild等。從zygote的path可以看出,它所在的應用程序名叫"app_process"。通過指定--zygote參數,app_process可以識別出用戶是否需要啓動zygote。
"app_process"程序源碼路徑在:android-8.0.0_r1\frameworks\base\cmds\app_process\app_main.cpp中。

app_process_path.png

android-8.0.0_r1\frameworks\base\cmds\app_process\Android.mk主要內容:

LOCAL_SRC_FILES:= \
    app_main.cpp

LOCAL_LDFLAGS := -Wl,--version-script,art/sigchainlib/version-script.txt -Wl,--export-dynamic

LOCAL_SHARED_LIBRARIES := \
    libdl \
    libcutils \
    libutils \
    liblog \
    libbinder \
    libnativeloader \
    libandroid_runtime \
    $(app_process_common_shared_libs) \

LOCAL_WHOLE_STATIC_LIBRARIES := libsigchain

LOCAL_MODULE:= app_process

"app_process"的源碼路徑在:
android-8.0.0_r1\frameworks\base\cmds\app_process\app_main.cpp
其主要函數:

int main(int argc, char* const argv[])
{
    ...
    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));

    // After the parent dir, we expect one or more the following internal
    // arguments :
    //
    // --zygote : Start in zygote mode
    // --start-system-server : Start the system server.
    // --application : Start in application (stand alone, non zygote) mode.
    // --nice-name : The nice name for this process.


    // Parse runtime arguments.  Stop at first unrecognized option.
    bool zygote = false;
    bool startSystemServer = false;
    bool application = false;
    String8 niceName;
    String8 className;

    ++i;  // Skip unused "parent dir" argument.
    while (i < argc) {
        const char* arg = argv[i++];
        if (strcmp(arg, "--zygote") == 0) {
            zygote = true;
            niceName = ZYGOTE_NICE_NAME;
        } else if (strcmp(arg, "--start-system-server") == 0) {
            startSystemServer = true;
        } else if (strcmp(arg, "--application") == 0) {
            application = true;
        } else if (strncmp(arg, "--nice-name=", 12) == 0) {
            niceName.setTo(arg + 12);
        } else if (strncmp(arg, "--", 2) != 0) {
            className.setTo(arg);
            break;
        } else {
            --i;
            break;
        }
    }

    Vector<String8> args;
    if (!className.isEmpty()) {
        // We're not in zygote mode, the only argument we need to pass
        // to RuntimeInit is the application argument.
        //
        // The Remainder of args get passed to startup class main(). Make
        // copies of them before we overwrite them with the process name.
        args.add(application ? String8("application") : String8("tool"));
        runtime.setClassNameAndArgs(className, argc - i, argv + i);
    } else {
        // We're in zygote mode.
        maybeCreateDalvikCache();

        if (startSystemServer) {
            args.add(String8("start-system-server"));
        }

        char prop[PROP_VALUE_MAX];
        if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) {
            LOG_ALWAYS_FATAL("app_process: Unable to determine ABI list from property %s.",
                ABI_LIST_PROPERTY);
            return 11;
        }

        String8 abiFlag("--abi-list=");
        abiFlag.append(prop);
        args.add(abiFlag);

        // In zygote mode, pass all remaining arguments to the zygote
        // main() method.
        for (; i < argc; ++i) {
            args.add(String8(argv[i]));
        }
    }

    if (!niceName.isEmpty()) {
        runtime.setArgv0(niceName.string());
        set_process_name(niceName.string());
    }

    if (zygote) {
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    } else if (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.");
        return 10;
    }
}

因爲,在此init.rc指定了--zygote選項,因而app_process接下來將啓動"ZygoteInit"並傳入"start-system-server"。
AppRuntime 繼承自AndroidRuntime,所以,runtime.start()函數對應源碼:
android-8.0.0_r1\frameworks\base\core\jni\AndroidRuntime.cpp

 

void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
...
    /* start the virtual machine */
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    JNIEnv* env;
    if (startVm(&mJavaVM, &env, zygote) != 0) {//啓動虛擬機
        return;
    }
    onVmCreated(env);//虛擬機啓動後的回調

    /*
     * Register android functions.
     */
    if (startReg(env) < 0) {
        ALOGE("Unable to register all android natives\n");
        return;
    }

...

}

除了與裝載各種系統類(具體實現在ZygoteInit#preload()這個方法裏)外,ZygoteInit的另一個重要工作就是啓動SystemServer---這是大部分Android系統服務(由Java語言編寫)的所在地。

3.3 SystemServer(Android的系統服務)

       SystemServer是Android進入Laucher前的最後準備。
       一旦在init.rc中爲zygote指定了啓動參數--start-system-server,那麼ZygoteInit就會調用startSystemServer來啓動SystemServer。

    private static boolean startSystemServer(String abiList, String socketName, ZygoteServer zygoteServer)
            throws Zygote.MethodAndArgsCaller, RuntimeException {
       ...
        /* Hardcoded command line to start the system server */
        String args[] = {
            "--setuid=1000",
            "--setgid=1000",
            "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,1032,3001,3002,3003,3006,3007,3009,3010",
            "--capabilities=" + capabilities + "," + capabilities,
            "--nice-name=system_server",
            "--runtime-args",
            "com.android.server.SystemServer",
        };
        ZygoteConnection.Arguments parsedArgs = null;

        int pid;

        try {
            parsedArgs = new ZygoteConnection.Arguments(args);
            ...
            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);
            }

            zygoteServer.closeServerSocket();
            handleSystemServerProcess(parsedArgs);
        }

        return true;
    }

       根據fork的特性,子進程和父進程將獲得同樣的代碼環境。當變量pid值爲0時,說明是子進程,否則是父進程;如果是前者的話,則進一步調用handleSystemServerProcess來完成剩下的工作,也是最核心的部分---啓動各種系統服務。並在一切準備就緒後進入Launcher主界面。

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