Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 安卓啟動流程

安卓啟動流程

編輯:關於Android編程

看了很多相關博客,今天也來自己梳理以下~~~
Android從Linux系統啟動

init進程啟動
Native服務啟動
System Server, Android 服務啟動
Home啟動

總體啟動框架:

2012111315182764.jpg

Init進程啟動<喎?/kf/ware/vc/" target="_blank" class="keylink">vc3Ryb25nPjwvcD4NCjxibG9ja3F1b3RlPg0KCTxwPsrXz8h1Ym9vdNL9tbxMaW51eMTausvG9Lavo6zIu7rz1NrTw7unv9W85NbQxvS2r2luaXS9+LPMo6zU2cb0tq/G5Mv7z7XNs734s8yho9Taz7XNs8b0tq/N6rPJzeqzybrzo6xpbml0vaux5M6qyti7pL34s8y84MrTz7XNs8bky/u9+LPMoaM8YSBocmVmPQ=="http://lib.csdn.net/base/15">Android是基於Linux的操作系統,所以init也是Android系統中用戶空間的第一個進程,它的進程號是1。

\

Init的主要職責是:

作為守護進程
解析核執行init.rc文件
生成設備節點
屬性服務

源碼在/system/core/init/init.c

int main(int argc, char **argv) {
    //啟動uevent守護進程
    if (!strcmp(basename(argv[0]), "ueventd"))
        return ueventd_main(argc, argv);

    //啟動看門狗守護進程
    if (!strcmp(basename(argv[0]), "watchdogd"))
        return watchdogd_main(argc, argv);

    umask(0);
    //創建並掛在啟動所需的文件目錄 
    mkdir("/dev", 0755);
    mkdir("/proc", 0755);
    mkdir("/sys", 0755);

    mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755");
    mkdir("/dev/pts", 0755);
    mkdir("/dev/socket", 0755);
    mount("devpts", "/dev/pts", "devpts", 0, NULL);
    mount("proc", "/proc", "proc", 0, NULL);
    mount("sysfs", "/sys", "sysfs", 0, NULL);

    close(open("/dev/.booting", O_WRONLY | O_CREAT, 0000));

    //重定向標准輸入/輸出/錯誤輸出到/dev/_null_
    open_devnull_stdio();
    klog_init();//log初始化 
    property_init();//屬性服務初始化  

    //從/proc/cpuinfo中讀取Hardware名,在後面的mix_hwrng_into_linux_rng_action函 數中會將hardware的值設置給屬性ro.hardware  
    get_hardware_name(hardware, &revision);
    //導入並設置內核變量  
    process_kernel_cmdline();
    ......
    INFO("property init\n");
    if (!is_charger)
        property_load_boot_defaults();

    INFO("reading config file\n");
    init_parse_config_file("/init.rc");//解析init.rc配置文件
    /* 
     * 解析完init.rc後會得到一系列的action等,下面的代碼將執行處於early-init階段的 action。 
     * init將action按照執行時間段的不同分為early-init、init、early-boot、boot。 
     * 進行這樣的劃分是由於有些動作之間具有依賴關系,某些動作只有在其他動作完成後才能執行,所以就有了先後的區別。 
     * 具體哪些動作屬於哪個階段是在init.rc中的配置決定的 
     */ 
    action_for_each_trigger("early-init", action_add_queue_tail);
    ......

    for(;;) {//init進入無限循環
        ......
        execute_one_command();
        restart_processes();//重啟已經死去的進程 
        ...... 
        nr = poll(ufds, fd_count, timeout); //等待事件發生
        if (nr <= 0)
            continue;

        for (i = 0; i < fd_count; i++) {
            if (ufds[i].revents == POLLIN) {
                if (ufds[i].fd == get_property_set_fd())//處理屬性服務事件 
                    handle_property_set_fd();
                else if (ufds[i].fd == get_keychord_fd())//處理keychord事件
                    handle_keychord();
                else if (ufds[i].fd == get_signal_fd())
                    handle_signal();//處理SIGCHLD信號事件
            }
        }
    }

    return 0;
}

看看init.rc腳本

service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
    class main
    socket zygote stream 660 root system
    onrestart write /sys/android_power/request_state wake
    onrestart write /sys/power/state on
    onrestart restart media
    onrestart restart netd

ps:(1)這裡描述了孵化器zygote的啟動(init是zygote的父進程,而系統服務進程system_server和其他所有的com.xxx結尾的應用程序都是從zygote fork 而來)。
(2)前面的關鍵字service告訴init進程創建一個名為”zygote”的進程,這個zygote進程要執行的程序是/system/bin/app_process,後面是要傳給app_process的參數。最後的一系列onrestart關鍵字表示這個zygote進程重啟時需要執行的命令。

了解了這個信息之後,我們就知道Zygote進程要執行的程序便是system/bin/app_process了,它的源代碼位於frameworks/base/cmds/app_process/app_main.cpp文件中,入口函數是main。

int main(int argc, char* const argv[])
{
     ......
    // These are global variables in ProcessState.cpp
    mArgC = argc;
    mArgV = argv;

    mArgLen = 0;
    for (int i=0; i

main函數的主要作用就是創建一個AppRuntime變量,然後調用它的start函數。它的定義也在同一文件app_main.cpp下面class AppRuntime : public AndroidRuntime
(AndroidRuntime的源碼在/frameworks/base/core/jni下,它是抽象基類);
在AndroidRuntime.h中定義了4種啟動模式

enum StartMode {
        Zygote,//啟動Zygote
        SystemServer,//啟動系統服務
        Application,//啟動應用程序
        Tool,//
    };

再看看具體的start函數做了什麼

/*
 * Start the Android runtime.  This involves starting the virtual machine
 * and calling the "static void main(String[] args)" method in the class
 * named by "className".
 *
 * Passes the main function two arguments, the class name and the specified
 * options string.
 */
//上面的解釋是開始android運行時環境。將開始虛擬機,然後用類似反射的機制去調用類名為參數className的main()方法!
void AndroidRuntime::start(const char* className, const char* options)
{
    if (strcmp(options, "start-system-server") == 0) {
        /* track our progress through the boot sequence */
        const int LOG_BOOT_PROGRESS_START = 3000;
        LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START,
                       ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
    }

    const char* rootDir = getenv("ANDROID_ROOT");
    if (rootDir == NULL) {
        rootDir = "/system";
        if (!hasDir("/system")) {
            LOG_FATAL("No root directory specified, and /android does not exist.");
            return;
        }
        setenv("ANDROID_ROOT", rootDir, 1);
    }

    /* start the virtual machine */
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    JNIEnv* env;
    if (startVm(&mJavaVM, &env) != 0) {//開啟虛擬機
        return;
    }
    onVmCreated(env);

    /*
     * Register android functions. 注冊本地native函數
     */
    if (startReg(env) < 0) {
        ALOGE("Unable to register all android natives\n");
        return;
    }
    jclass stringClass;
    jobjectArray strArray;
    jstring classNameStr;
    jstring optionsStr;

    stringClass = env->FindClass("java/lang/String");
    assert(stringClass != NULL);
    strArray = env->NewObjectArray(2, stringClass, NULL);
    assert(strArray != NULL);
    classNameStr = env->NewStringUTF(className);
    assert(classNameStr != NULL);
    env->SetObjectArrayElement(strArray, 0, classNameStr);
    optionsStr = env->NewStringUTF(options);
    env->SetObjectArrayElement(strArray, 1, optionsStr);

    /*
     * Start VM.  This thread becomes the main thread of the VM, and will
     * not return until the VM exits.
     */
    //激活虛擬機,當前線程變成虛擬機下的主線程。
    char* slashClassName = toSlashClassName(className);
    jclass startClass = env->FindClass(slashClassName);
    if (startClass == NULL) {
        ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
    } else {
        jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
            "([Ljava/lang/String;)V");
        if (startMeth == NULL) {
            ALOGE("JavaVM unable to find main() in '%s'\n", className);
            /* keep going */
        } else {
            env->CallStaticVoidMethod(startClass, startMeth, strArray);
        }
    }

}

通過源代碼的分析知道,其實上面主要是給一個應用程序分配一個虛擬機環境(虛擬機拷貝),然後通過JNI的方式去調java裡某個className類的main()方法。

還記得runtime.start(“com.android.internal.os.ZygoteInit”, startSystemServer ? “start-system-server” : “”);

實際執行com.android.internal.os.ZygoteInit類的main()(源碼地址frameworks/base/core/java/com/android/internal/os/ZygoteInit.java):

public static void main(String argv[]) {
        try {
            // Start profiling the zygote initialization.
            SamplingProfilerIntegration.start();

            registerZygoteSocket();
            EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
                SystemClock.uptimeMillis());
            preload();
            EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
                SystemClock.uptimeMillis());

            // Finish profiling the zygote initialization.
            SamplingProfilerIntegration.writeZygoteSnapshot();

            // Do an initial gc to clean up after startup
            gc();
           ......

            // If requested, start system server directly from Zygote
            .......

            if (argv[1].equals("start-system-server")) {
                startSystemServer();//啟動system_server進程  
            } else if (!argv[1].equals("")) {
                throw new RuntimeException(argv[0] + USAGE_STRING);
            }
          ......
            runSelectLoop();
            closeServerSocket();
        } catch (MethodAndArgsCaller caller) {
            caller.run();
        } catch (RuntimeException ex) {
            ......
        }
    }

它主要作了三件事情:
1、調用registerZygoteSocket函數創建了一個socket接口,用來和ActivityManagerService通訊;
2、調用startSystemServer函數來啟動SystemServer組件;
3、調用runSelectLoopMode函數進入一個無限循環在前面創建的socket接口上等待ActivityManagerService請求創建新的應用程序進程。

這裡Zygote進程初始化完畢,開始大循環了~~~
仔細分析下第二步startSystemServer啟動系統服務組件

/**
     * Prepare the arguments and fork for the system server process.
     */
    private static boolean startSystemServer() throws 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,1032,3001,3002,3003,3006,3007",
            "--capabilities=" + capabilities + "," + capabilities,
            "--runtime-init",
            "--nice-name=system_server",
            "com.android.server.SystemServer",
        };
        ZygoteConnection.Arguments parsedArgs = null;

        int pid;

        try {
            parsedArgs = new ZygoteConnection.Arguments(args);
            ......

            /* Request to fork the system server process */
            pid = Zygote.forkSystemServer(
                    parsedArgs.uid, parsedArgs.gid,
                    parsedArgs.gids,
                    parsedArgs.debugFlags,
                    null,
                    parsedArgs.permittedCapabilities,
                    parsedArgs.effectiveCapabilities);
        } catch (IllegalArgumentException ex) {
            ......
        }

        /* For child process */
        if (pid == 0) {//pid==0說明是子進程,父進程為Zygote 
            handleSystemServerProcess(parsedArgs);
        }

        return true;
    }

在startSystemServer中先設置了Zygote.forkSystemServer所需的參數,然後通過forkSystemServer方法fork出SystemServer進程,最後通過handleSystemServerProcess處理新進程中的瑣事。

首先看一下參數:

1、setuid=1000,這裡1000代表SYSTEM_UID,即系統進程,關於進程ID的說明可以參見:/frameworks/base/core/java/android/os/Process.java。
2、nice-name=system_server表示制定進程的名字為“system_server”
3、com.android.server.SystemServer表示SystemServer類的位置。

接下來看一下forkSystemServer的實現:
libcore/dalvik/src/main/java/dalvik/system/Zygote.java

/**
     * Special method to start the system server process. In addition to the
     * common actions performed in forkAndSpecialize, the pid of the child
     * process is recorded such that the death of the child process will cause
     * zygote to exit.
     * 注意由zygote fork 出的system_service進程如果死了,則zygote進程也退出
     */
    public static int forkSystemServer(int uid, int gid, int[] gids, int debugFlags,
            int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
        preFork();
        int pid = nativeForkSystemServer(
                uid, gid, gids, debugFlags, rlimits, permittedCapabilities, effectiveCapabilities);
        postFork();
        return pid;
    }
    native public static int nativeForkSystemServer(int uid, int gid, int[] gids, int debugFlags,
            int[][] rlimits, long permittedCapabilities, long effectiveCapabilities);

forkSystemServer最後調nativeForkSystemServer,而它是通過JNI實現,源碼:/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);

    /* The zygote process checks whether the child process has died or not. */
    if (pid > 0) {//pid大於0,說明是在父進程中,Zygote進程往下執行
        int status;
        gDvm.systemServerPid = pid;
        /* There is a slight window that the system server process has crashed
         * but it went unnoticed because we haven't published its pid yet. So
         * we recheck here just to make sure that all is well.
         */
        if (waitpid(pid, &status, WNOHANG) == pid) {
            ALOGE("System server process %d has died. Restarting Zygote!", pid);
            kill(getpid(), SIGKILL);//一旦上面的等待返回,說明進程pid(system_server)已終止,此時Zygote殺死自己  
        }
    }
    RETURN_INT(pid);
}

//native函數注冊
const DalvikNativeMethod dvm_dalvik_system_Zygote[] = {
    { "nativeFork", "()I",
      Dalvik_dalvik_system_Zygote_fork },
    { "nativeForkAndSpecialize", "(II[II[[IILjava/lang/String;Ljava/lang/String;)I",
      Dalvik_dalvik_system_Zygote_forkAndSpecialize },
    { "nativeForkSystemServer", "(II[II[[IJJ)I",
      Dalvik_dalvik_system_Zygote_forkSystemServer },
    { NULL, NULL, NULL },
};

SystemServer創建之後交給handleSystemServerProcess處理!

回到 frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

   /**
     * Finish remaining work for the newly forked system server process.
     * 完成新建的system server進程的剩余工作
     */
    private static void handleSystemServerProcess(
            ZygoteConnection.Arguments parsedArgs)
            throws ZygoteInit.MethodAndArgsCaller {

        closeServerSocket();//關閉從Zygote復制過來的socket 

        // set umask to 0077 so new files and directories will default to owner-only permissions.
        Libcore.os.umask(S_IRWXG | S_IRWXO);//設置文件的默認權限,去除文件所有者之外的權限

        if (parsedArgs.niceName != null) {
            Process.setArgV0(parsedArgs.niceName);
        }

        if (parsedArgs.invokeWith != null) {
            WrapperInit.execApplication(parsedArgs.invokeWith,
                    parsedArgs.niceName, parsedArgs.targetSdkVersion,
                    null, parsedArgs.remainingArgs);
        } else {
            /*
             * Pass the remaining arguments to SystemServer.傳遞剩下的參數給SystemServer
             */
            RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs);
        }

        /* should never reach here */
    }

最後將參數往下傳給RuntimeInit.zygoteInit(,)
源碼:frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

   /**
     * The main function called when started through the zygote process. This
     * could be unified with main(), if the native code in nativeFinishInit()
     * were rationalized with Zygote startup.
     */
    public static final void zygoteInit(int targetSdkVersion, String[] argv)
            throws ZygoteInit.MethodAndArgsCaller {
        if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");

        redirectLogStreams();//將System.out 和 System.err 輸出重定向到Android 的Log系統 
    /* 
     * 初始化了一些系統屬性,其中最重要的一點就是設置了一個未捕捉異常的handler, 
     * 當代碼有任何未知異常,就會執行它, 
     * 調試過Android代碼的同學經常看到的"*** FATAL EXCEPTION IN SYSTEM PROCESS" 打印就出自這裡 
     */  
        commonInit();
    /* 
     * 最終會調用app_main的onZygoteInit函數 
     * 這裡的作用是在新進程中引入Binder,也就說通過nativeZygoteInit以後,新的進程就可以使用Binder進程通信了 
     */  
        nativeZygoteInit();

        applicationInit(targetSdkVersion, argv);//應用初始化
    }

   private static void applicationInit(int targetSdkVersion, String[] argv)
            throws ZygoteInit.MethodAndArgsCaller {
        // If the application calls System.exit(), terminate the process
        // immediately without running any shutdown hooks.  It is not possible to
        // shutdown an Android application gracefully.  Among other things, the
        // Android runtime shutdown hooks close the Binder driver, which can cause
        // leftover running threads to crash before the process actually exits.
        nativeSetExitWithoutCleanup(true);

        // We want to be fairly aggressive about heap utilization, to avoid
        // holding on to a lot of memory that isn't needed.
        VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
        VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);

        final Arguments args;
        try {
            args = new Arguments(argv);
        } catch (IllegalArgumentException ex) {
            Slog.e(TAG, ex.getMessage());
            // let the process exit
            return;
        }

        // Remaining arguments are passed to the start class's static main
        invokeStaticMain(args.startClass, args.startArgs);
    }

這裡invokeStaticMain的args.startClass的值為com.android.server.SystemServer。接下來SystemServer類的main函數將會被調用,我太機智了^~^。

源碼:frameworks/base/services/java/com/android/server/SystemServer.java

public static void main(String[] args) {

        /*
         * In case the runtime switched since last boot (such as when
         * the old runtime was removed in an OTA), set the system
         * property so that it is in sync.
         */
        SystemProperties.set("persist.sys.dalvik.vm.lib",
                             VMRuntime.getRuntime().vmLibrary());

        if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {//調整時間
            Slog.w(TAG, "System clock is before 1970; setting to 1970.");
            SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
        }
         ......

        // Mmmmmm... more memory!
        dalvik.system.VMRuntime.getRuntime().clearGrowthLimit();

        // The system server has to run all of the time, so it needs to be
        // as efficient as possible with its memory usage.
        VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);

        Environment.setUserRequired(true);

        System.loadLibrary("android_servers");

        Slog.i(TAG, "Entered the Android system server!");

        // Initialize native services.
        nativeInit();//初始化本地所以服務 > SensorService

        // This used to be its own separate thread, but now it is
        // just the loop we run on the main thread.
        ServerThread thr = new ServerThread();
        thr.initAndLoop();
    }

在main中會加載libandroid_servers.so庫,然後調用nativeInit初始化native層的Service。
ServerThread初始化一堆android服務。

小結一下:

Linux的init在啟動若干守護進程之後,就啟動了Android的runtime和zygote,Zygote進程負責後續Android應用程序框架層的其它進程的創建和啟動工作。

Zygote進程會首先創建一個SystemServer進程,SystemServer進程負責啟動系統的關鍵服務,如包管理服務PackageManagerService和應用程序組件管理服務ActivityManagerService。

當我們需要啟動一個Android應用程序時,ActivityManagerService會通過Socket進程間通信機制,通知Zygote進程為這個應用程序創建一個新的進程。
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved