Android7.0系統(tǒng)啟動

    首先由Bootloader加載配置引導(dǎo)啟動Linux內(nèi)核,Linux kernal啟動之后才會啟動Android系統(tǒng)糖声。

1,啟動init進程

在Linux內(nèi)核啟動后蒋情,會開啟第一個android用戶進程Init(\system\core\init\init.cpp),關(guān)鍵代碼如下:

int main(int argc, char** argv) {
    ......
    if (is_first_stage) {
        boot_clock::time_point start_time = boot_clock::now();
        // Clear the umask.設(shè)置創(chuàng)建文件時的默認(rèn)權(quán)限
        umask(0);
        // Get the basic filesystem setup we need put together in the initramdisk
        // on / and then we'll let the rc file figure out the rest.
        mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755");
        mkdir("/dev/pts", 0755);
        mkdir("/dev/socket", 0755);
    
        ......
    }
    // At this point we're in the second stage of init.
    InitKernelLogging(argv);
    LOG(INFO) << "init second stage started!";
    ...... // 一些初始化操作
    ActionManager& am = ActionManager::GetInstance();
    ServiceManager& sm = ServiceManager::GetInstance();
    Parser& parser = Parser::GetInstance();
    parser.AddSectionParser("service", std::make_unique<ServiceParser>(&sm));
    parser.AddSectionParser("on", std::make_unique<ActionParser>(&am));
    parser.AddSectionParser("import", std::make_unique<ImportParser>(&parser));
    std::string bootscript = GetProperty("ro.boot.init_rc", "");
    if (bootscript.empty()) {
        // 解析init.rc文件
        parser.ParseConfig("/init.rc");
        parser.set_is_system_etc_init_loaded(
                parser.ParseConfig("/system/etc/init"));
        parser.set_is_vendor_etc_init_loaded(
                parser.ParseConfig("/vendor/etc/init"));
        parser.set_is_odm_etc_init_loaded(parser.ParseConfig("/odm/etc/init"));
    } else {
        parser.ParseConfig(bootscript);
        parser.set_is_system_etc_init_loaded(true);
        parser.set_is_vendor_etc_init_loaded(true);
        parser.set_is_odm_etc_init_loaded(true);
    }
    ......
    return 0;
}

2暂刘,啟動zygote進程

在init.cpp的main方法中會解析init.rc文件(\system\core\rootdir\init.rc)如贷,該文件是通過AIL(Android Init Language)語言定義的初始化文件漾根,具體語法規(guī)則在\system\core\init\README.md文件厚宰。在init.rc文件中通過下面的語句引入了zygote進程的配置信息腌巾。

import /init.${ro.zygote}.rc

具體的配置信息以init.zygote32.rc(\system\core\rootdir\init.zygote32.rc)文件為例:其中包括zygote的用戶、組铲觉、優(yōu)先級澈蝙、以及重啟時的操作信息。

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

通過init.zygote32.rc配置信息可以知道zygote的源文件在/system/bin/app_process目錄撵幽,即app_main.cpp
(源文件\frameworks\base\cmds\app_process\app_main.cpp)灯荧,下面是該文件的注釋,由此可見該文件是應(yīng)用進程的入口盐杂。

/*
 * Main entry of app process.
 *
 * Starts the interpreted runtime, then starts up the application.
 *
 */

該文件的main方法如下:

int main(int argc, char* const argv[])
{
    ......

    // 安卓運行時
    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
    // Process command line arguments
    // ignore argv[0]逗载,第一個參數(shù)忽略
    argc--;
    argv++;

    // 配置runtime
    ......
    // 解析runtime的參數(shù),并且忽略掉第一個無效的參數(shù)
    bool zygote = false;
    bool startSystemServer = false;
    
    ......
    if (zygote) {
        // 如果zygote進程沒有啟動就啟動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.");
    }
}

app_main.cpp執(zhí)行完畢之后况褪,正式從c/c++部分轉(zhuǎn)到j(luò)ava部分執(zhí)行ZygoteInit(\frameworks\base\core\java\com\android
internal\os\ZygoteInit.java)進程,通過該文件的注釋可以了解到該進程中的主要操作有:預(yù)加載一些類更耻,等待socket中的一些命令测垛。

/**
 * Startup class for the zygote process.
 *
 * Pre-initializes some classes, and then waits for commands on a UNIX domain
 * socket. Based on these commands, forks off child processes that inherit
 * the initial state of the VM.
 *
 */

ZygoteInit.java中main方法如下:

public static void main(String argv[]) {
        ZygoteServer zygoteServer = new ZygoteServer();
        // Mark zygote start. This ensures that thread creation will throw
        // an error.
        ZygoteHooks.startZygoteNoThreadCreation();
        // Zygote goes into its own process group.
        // 將進程pid設(shè)置為0
        try {
            Os.setpgid(0, 0);
        } catch (ErrnoException ex) {
            throw new RuntimeException("Failed to setpgid(0,0)", ex);
        }
        try {
            // 注冊監(jiān)聽
            zygoteServer.registerServerSocket(socketName);
            // 預(yù)加載一些關(guān)鍵的類
            preload();

            ......
            // Zygote process unmounts root storage spaces.
            Zygote.nativeUnmountStorageOnInit();
            // Set seccomp policy
            Seccomp.setPolicy();
            ZygoteHooks.stopZygoteNoThreadCreation();
            if (startSystemServer) {
                // 開啟SystemServer
                startSystemServer(abiList, socketName, zygoteServer);
            }
            zygoteServer.closeServerSocket();
        } catch (Zygote.MethodAndArgsCaller caller) {
            caller.run();
        } catch (Throwable ex) {
            Log.e(TAG, "System zygote died with exception", ex);
            zygoteServer.closeServerSocket();
            throw ex;
        }
    }

其中preload()方法如下:加載android系統(tǒng)及應(yīng)用運行所必要的資源和類(通過preloadClassess()預(yù)加載類文件)

static void preload() {
        Log.d(TAG, "begin preload");
        Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "BeginIcuCachePinning");
        beginIcuCachePinning();
        Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
        Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadClasses");
        preloadClasses();
        Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
        Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadResources");
        preloadResources();
        Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
        Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadOpenGL");
        preloadOpenGL();
        Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
        preloadSharedLibraries();
        preloadTextResources();
        // Ask the WebViewFactory to do any initialization that must run in the zygote process,
        // for memory sharing purposes.
        WebViewFactory.prepareWebViewInZygote();
        endIcuCachePinning();
        warmUpJcaProviders();
        Log.d(TAG, "end preload");
    }

預(yù)加載的類信息配置,源文件目錄(\frameworks\base\preloaded-classes)

  /**
    * The path of a file that contains classes to preload.
    */
    private static final String PRELOADED_CLASSES = "/system/etc/preloaded-classes";

3秧均,啟動SystemServer進程

在ZygoteInit.java的main方法中會調(diào)用startSystemServer()來開啟SystemServer進程:

/**
     * Prepare the arguments and fork for the system server process.
     */
    private static boolean startSystemServer(String abiList, String socketName, ZygoteServer zygoteServer)
            throws Zygote.MethodAndArgsCaller, RuntimeException {
.......   
        /* Hardcoded command line to start the system server */
        // 硬編碼的命令行來開啟system server
        String args[] = {
            "--setuid=1000",
            "--setgid=1000",
            "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1032,3001,3002,3003,3006,3007,3009,3010",
            "--capabilities=" + capabilities + "," + capabilities,
            "--nice-name=system_server",
            "--runtime-args",
            "com.android.server.SystemServer",
        };
        
        ......

    }

SystemServer的源文件目錄(\frameworks\base\services\java\com\android\server\SystemServer.java)食侮,其中main方法中直接調(diào)用了自己的run方法号涯。在run方法中會開啟一系列的服務(wù),并調(diào)用Looper.prepareMainLooper()和Looper.loop()方法初始化主線程的消息循環(huán)锯七。

   /**
     * The main entry point from zygote.
     */
    public static void main(String[] args) {
        new SystemServer().run();
    }
private void run() {
        try {
            // Mmmmmm... more memory!
            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);
            // Some devices rely on runtime fingerprint generation, so make sure
            // we've defined it before booting further.
            Build.ensureFingerprintProperty();
            // Within the system server, it is an error to access Environment paths without
            // explicitly specifying a user.
            Environment.setUserRequired(true);
            // Within the system server, any incoming Bundles should be defused
            // to avoid throwing BadParcelableException.
            BaseBundle.setShouldDefuse(true);
            // Ensure binder calls into the system always run at foreground priority.
            BinderInternal.disableBackgroundScheduling(true);
            // Increase the number of binder threads in system_server
            BinderInternal.setMaxThreads(sMaxBinderThreads);
            // Prepare the main looper thread (this thread).
            android.os.Process.setThreadPriority(
                android.os.Process.THREAD_PRIORITY_FOREGROUND);
            android.os.Process.setCanSelfBackground(false);
            // 此處調(diào)用Looper.prepareMainLooper()方法初始化主線程中Looper
            Looper.prepareMainLooper();
            // Initialize native services.
            System.loadLibrary("android_servers");
            // Check whether we failed to shut down last time we tried.
            // This call may not return.
            performPendingShutdown();
            // Initialize the system context.
            createSystemContext();
            // Create the system service manager.
            mSystemServiceManager = new SystemServiceManager(mSystemContext);
            mSystemServiceManager.setRuntimeRestarted(mRuntimeRestart);
            LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
        }
        // Start services.
        try {
            Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartServices");
            // 開啟輔助服務(wù)链快,包括傳感器,亮度
            startBootstrapServices();
            // 開啟核心服務(wù)眉尸,BatteryService域蜗,UsageStatsService,WebViewUpdateService
            startCoreServices();
            // 開啟一些其它的服務(wù):VibratorService噪猾,NetworkManagementService霉祸,ConnectivityService,NetworkStatsService...
            startOtherServices();
        } catch (Throwable ex) {
            Slog.e("System", "******************************************");
            Slog.e("System", "************ Failure starting system services", ex);
            throw ex;
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
        }
        // Loop forever.
        Looper.loop();

    }
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末袱蜡,一起剝皮案震驚了整個濱河市丝蹭,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌坪蚁,老刑警劉巖奔穿,帶你破解...
    沈念sama閱讀 211,042評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異敏晤,居然都是意外死亡贱田,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評論 2 384
  • 文/潘曉璐 我一進店門茵典,熙熙樓的掌柜王于貴愁眉苦臉地迎上來湘换,“玉大人,你說我怎么就攤上這事统阿〔室校” “怎么了?”我有些...
    開封第一講書人閱讀 156,674評論 0 345
  • 文/不壞的土叔 我叫張陵扶平,是天一觀的道長帆离。 經(jīng)常有香客問我,道長结澄,這世上最難降的妖魔是什么哥谷? 我笑而不...
    開封第一講書人閱讀 56,340評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮麻献,結(jié)果婚禮上们妥,老公的妹妹穿的比我還像新娘。我一直安慰自己勉吻,他們只是感情好监婶,可當(dāng)我...
    茶點故事閱讀 65,404評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般惑惶。 火紅的嫁衣襯著肌膚如雪煮盼。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,749評論 1 289
  • 那天带污,我揣著相機與錄音僵控,去河邊找鬼。 笑死鱼冀,一個胖子當(dāng)著我的面吹牛报破,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播雷绢,決...
    沈念sama閱讀 38,902評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼泛烙,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了翘紊?” 一聲冷哼從身側(cè)響起蔽氨,我...
    開封第一講書人閱讀 37,662評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎帆疟,沒想到半個月后鹉究,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,110評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡踪宠,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年自赔,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片柳琢。...
    茶點故事閱讀 38,577評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡绍妨,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出柬脸,到底是詐尸還是另有隱情他去,我是刑警寧澤,帶...
    沈念sama閱讀 34,258評論 4 328
  • 正文 年R本政府宣布倒堕,位于F島的核電站灾测,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏垦巴。R本人自食惡果不足惜媳搪,卻給世界環(huán)境...
    茶點故事閱讀 39,848評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望骤宣。 院中可真熱鬧秦爆,春花似錦、人聲如沸憔披。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至精刷,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間蔗候,已是汗流浹背怒允。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留锈遥,地道東北人纫事。 一個月前我還...
    沈念sama閱讀 46,271評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像所灸,于是被迫代替她去往敵國和親丽惶。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,452評論 2 348

推薦閱讀更多精彩內(nèi)容