zygote

本文主要介紹zygote 流程

frameworks/base/cmds/app_process/app_main.cpp
frameworks/base/core/jni/AndroidRuntime.cpp
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
frameworks/base/core/java/com/android/internal/os/Zygote.java
zygote
zygote uml

1 皱埠, 解析zygote 腳本故黑,并運行main
android/system/core/rootdir/init.zygote64.rc

service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
    class main --> 啟動app_process  可執(zhí)行文件
    priority -20
    user root
    group root readproc
    socket zygote stream 660 root system---》創(chuàng)建/dev/socket/zygote
    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

frameworks/base/cmds/app_process/app_main.cpp

int main(int argc, char* const argv[])
{
    while (i < argc) {  -----》解析zygote rc 中的參數(shù)
        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;
    }
    ...........
    if (zygote) {
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);---->啟動zygote 
    } else if (className) {
        runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
    } 
}

2 啟動VM JNI
從該函數(shù) cpp-->java 啟動java虛擬機
frameworks/base/core/jni/AndroidRuntime.cpp

/*
 * 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". --->仔細(xì)看這里的說明
 * Passes the main function two arguments, the class name and the specified
 * options string.
 */
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
    JNIEnv* env;
    if (startVm(&mJavaVM, &env, zygote) != 0) {----------》啟動VM
        return;
    }
    onVmCreated(env);

    /*
     * Register android functions.-------------》啟動JNI 環(huán)境
     */
    if (startReg(env) < 0) {
        ALOGE("Unable to register all android natives\n");
        return;
    }

    /*
     * Start VM.  This thread becomes the main thread of the VM, and will
     * not return until the VM exits.
     */
    char* slashClassName = toSlashClassName(className != NULL ? className : "");
    jclass startClass = env->FindClass(slashClassName);
    if (startClass == NULL) {
        ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
        /* keep going */
    } 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);---->啟動main , zygote init
        }
}

3 注冊socket 加載資源 fork 等待
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

    public static void main(String argv[]) {
        ZygoteServer zygoteServer = new ZygoteServer();

            for (int i = 1; i < argv.length; i++) {------->保存init.rc中設(shè)定zygote 參數(shù)
                if ("start-system-server".equals(argv[i])) {
                    startSystemServer = true;
                } else if ("--enable-lazy-preload".equals(argv[i])) {
                    enableLazyPreload = true;
                } else if (argv[i].startsWith(ABI_LIST_ARG)) {
                    abiList = argv[i].substring(ABI_LIST_ARG.length());
                } else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
                    socketName = argv[i].substring(SOCKET_NAME_ARG.length());
                } else {
                    throw new RuntimeException("Unknown command line argument: " + argv[i]);
                }
            }

            zygoteServer.registerServerSocket(socketName);--------》注冊socket 
            preload(bootTimingsTraceLog);------》加載系統(tǒng)資源

            if (startSystemServer) {---------->第一次首先fork SystemServer, SystemServer單獨講解
                Runnable r = forkSystemServer(abiList, socketName, zygoteServer);
            }

       caller = zygoteServer.runSelectLoop(abiList);------》
-----》zygot 進入run selectloop. ---》connection.processOneCommand(this)----》forkAndSpecialize

    }

frameworks/base/core/java/com/android/internal/os/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.
     *
     * @param uid the UNIX uid that the new process should setuid() to after
     * fork()ing and and before spawning any threads.
     * @param gid the UNIX gid that the new process should setgid() to after
     * fork()ing and and before spawning any threads.
     * @param gids null-ok; a list of UNIX gids that the new process should
     * setgroups() to after fork and before spawning any threads.
     * @param debugFlags bit flags that enable debugging features.
     * @param rlimits null-ok an array of rlimit tuples, with the second
     * dimension having a length of 3 and representing
     * (resource, rlim_cur, rlim_max). These are set via the posix
     * setrlimit(2) call.
     * @param permittedCapabilities argument for setcap()
     * @param effectiveCapabilities argument for setcap()
     *
     * @return 0 if this is the child, pid of the child
     * if this is the parent, or -1 on error.
     */
    public static int forkSystemServer(int uid, int gid, int[] gids, int debugFlags,
            int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
        VM_HOOKS.preFork();
        // Resets nice priority for zygote process.
        resetNicePriority();--->rest 優(yōu)先級
        int pid = nativeForkSystemServer(---->進入naitive C++ 函數(shù), 進行了fork
                uid, gid, gids, debugFlags, rlimits, permittedCapabilities, effectiveCapabilities);
        // Enable tracing as soon as we enter the system_server.
        if (pid == 0) {
            Trace.setTracingEnabled(true, debugFlags);
        }
        VM_HOOKS.postForkCommon();
        return pid;
    }

4 資源加載解析preload
啟動過程中使用到了preload, 到底加載了哪些系統(tǒng)資源,共享資源進行預(yù)加載搀崭,獨立的app運行粗卜,基本是使用過程加載。在preload整個過程中是禁止多線程桥爽。

    static void preload(TimingsTraceLog bootTimingsTraceLog) {
        Log.d(TAG, "begin preload");
        preloadClasses();  ------》加載class 
        preloadResources();   ---->加載resource
        nativePreloadAppProcessHALs();  ---->加載 APP hal resource
        preloadOpenGL();  ---->加載openGL 資源
        preloadSharedLibraries();---->加載共享庫
        preloadTextResources();---->加載Text 資源
    }

frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
preloadClasses:基本思路朱灿,是讀取,while line by line , 解析加載钠四。

private static String PRELOADED_CLASSES = "/system/etc/preloaded-classes";-->class 路徑
InputStream is = new FileInputStream(PRELOADED_CLASSES);  --》讀取流
BufferedReader br = new BufferedReader(new InputStreamReader(is), 256); -->讀取到buf
    while ((line = br.readLine()) != null) {  ---->line讀取
           try {
                // Load and explicitly initialize the given class. Use
                // Class.forName(String, boolean, ClassLoader) to avoid repeated stack lookups
                // (to derive the caller's class-loader). Use true to force initialization, and
                // null for the boot classpath class-loader (could as well cache the
                // class-loader of this class in a variable).
                Class.forName(line, true, null);------》上面解析基本說明了盗扒,class.forName()方法內(nèi)部調(diào)用了this.getClass().getClassLoader()方法
                count++;
            } catch (ClassNotFoundException e) {
}

frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
frameworks/base/config/ preloaded-classes
只列舉部分的class , 因此通過Class.forName加載到系統(tǒng)中,生成字節(jié)碼缀去,系統(tǒng)啟動過程需要一定時間

android.R$styleable
android.accessibilityservice.AccessibilityServiceInfo$1
android.accounts.Account
android.accounts.Account$1
android.accounts.AccountManager
android.accounts.AccountManager$1
android.accounts.AccountManager$11
android.accounts.AccountManager$AmsTask
android.accounts.AccountManager$AmsTask$1
android.accounts.AccountManager$AmsTask$Response
android.accounts.AccountManager$BaseFutureTask
android.accounts.AccountManager$BaseFutureTask$1
android.accounts.AccountManager$BaseFutureTask$Response
android.accounts.AccountManager$Future2Task
android.accounts.AccountManagerFuture
............

frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
preloadResources:

    /**
     * Load in commonly used resources, so they can be shared across
     * processes.
     *
     * These tend to be a few Kbytes, but are frequently in the 20-40K
     * range, and occasionally even larger.
     */
    private static void preloadResources() {
        final VMRuntime runtime = VMRuntime.getRuntime();

        try {
            mResources = Resources.getSystem();
            mResources.startPreloading();
            if (PRELOAD_RESOURCES) {
                Log.i(TAG, "Preloading resources...");

                long startTime = SystemClock.uptimeMillis();
                TypedArray ar = mResources.obtainTypedArray(--------》加載
                        com.android.internal.R.array.preloaded_drawables);
                int N = preloadDrawables(ar);
                ar.recycle();
                Log.i(TAG, "...preloaded " + N + " resources in "
                        + (SystemClock.uptimeMillis()-startTime) + "ms.");

                startTime = SystemClock.uptimeMillis();
                ar = mResources.obtainTypedArray(--------》加載
                        com.android.internal.R.array.preloaded_color_state_lists);
                N = preloadColorStateLists(ar);
                ar.recycle();
                Log.i(TAG, "...preloaded " + N + " resources in "
                        + (SystemClock.uptimeMillis()-startTime) + "ms.");

                if (mResources.getBoolean(--------》加載
                        com.android.internal.R.bool.config_freeformWindowManagement)) {
                    startTime = SystemClock.uptimeMillis();
                    ar = mResources.obtainTypedArray(---------》加載
                            com.android.internal.R.array.preloaded_freeform_multi_window_drawables);
                   
                    //preloaded_freeform_multi_window_drawables 路徑是:
                    frameworks/base/core/res/res/values/arrays.xml
                    上面的資源類似與apk 中l(wèi)ayout 中的資源侣灶,window窗口大小,包括app 窗口

                    N = preloadDrawables(ar);
                    ar.recycle();
                    Log.i(TAG, "...preloaded " + N + " resource in "
                            + (SystemClock.uptimeMillis() - startTime) + "ms.");
                }
            }
            mResources.finishPreloading();
        } catch (RuntimeException e) {
            Log.w(TAG, "Failure preloading resources", e);
        }
    }

frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
preloadColorStateLists
下面是具體的參數(shù)TypedArray:
com.android.internal.R.array.preloaded_color_state_lists

    private static int preloadColorStateLists(TypedArray ar) {
        int N = ar.length();
        for (int i=0; i<N; i++) {
            int id = ar.getResourceId(i, 0);
            if (false) {
                Log.v(TAG, "Preloading resource #" + Integer.toHexString(id));
            }
            if (id != 0) {
                if (mResources.getColorStateList(id, null) == null) {
                    throw new IllegalArgumentException(
                            "Unable to find preloaded color resource #0x"
                            + Integer.toHexString(id)
                            + " (" + ar.getString(i) + ")");
                }
            }
        }
        return N;
    }

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

public static void main(String argv[]) {
     // Mark zygote start. This ensures that thread creation will throw an error.
     ZygoteHooks.startZygoteNoThreadCreation();  -------->開始禁止多線程

     registerServerSocket --->注冊socket
     preload(bootTimingsTraceLog);--->加載資源       
     gcAndFinalize(); ---> // Do an initial gc to clean up after startup 
     ZygoteHooks.stopZygoteNoThreadCreation()-------->停止禁止多線程
     Runnable r = forkSystemServer(abiList, socketName, zygoteServer)
}
禁止多線程

4 zygote 的socket 通信
zygote 創(chuàng)建了/dev/socket/zygote , 系統(tǒng)如何調(diào)用socket 創(chuàng)建通信朵耕, 在下面的文章中進行講解registerServerSocket

zygoteInit::main--->
         registerServerSocket--->
         preload---->
         forkSystemServer--->

總體概述:
https://www.cnblogs.com/monsterdev/p/12685091.html
https://blog.csdn.net/chz429/article/details/87514718

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末炫隶,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子阎曹,更是在濱河造成了極大的恐慌伪阶,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,188評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件处嫌,死亡現(xiàn)場離奇詭異栅贴,居然都是意外死亡,警方通過查閱死者的電腦和手機熏迹,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評論 3 395
  • 文/潘曉璐 我一進店門檐薯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人注暗,你說我怎么就攤上這事坛缕。” “怎么了捆昏?”我有些...
    開封第一講書人閱讀 165,562評論 0 356
  • 文/不壞的土叔 我叫張陵赚楚,是天一觀的道長。 經(jīng)常有香客問我骗卜,道長宠页,這世上最難降的妖魔是什么左胞? 我笑而不...
    開封第一講書人閱讀 58,893評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮举户,結(jié)果婚禮上烤宙,老公的妹妹穿的比我還像新娘。我一直安慰自己俭嘁,他們只是感情好躺枕,可當(dāng)我...
    茶點故事閱讀 67,917評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著供填,像睡著了一般屯远。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上捕虽,一...
    開封第一講書人閱讀 51,708評論 1 305
  • 那天慨丐,我揣著相機與錄音,去河邊找鬼泄私。 笑死房揭,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的晌端。 我是一名探鬼主播捅暴,決...
    沈念sama閱讀 40,430評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼咧纠!你這毒婦竟也來了蓬痒?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,342評論 0 276
  • 序言:老撾萬榮一對情侶失蹤漆羔,失蹤者是張志新(化名)和其女友劉穎梧奢,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體演痒,經(jīng)...
    沈念sama閱讀 45,801評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡亲轨,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,976評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了鸟顺。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片惦蚊。...
    茶點故事閱讀 40,115評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖讯嫂,靈堂內(nèi)的尸體忽然破棺而出蹦锋,到底是詐尸還是另有隱情,我是刑警寧澤欧芽,帶...
    沈念sama閱讀 35,804評論 5 346
  • 正文 年R本政府宣布莉掂,位于F島的核電站,受9級特大地震影響渐裸,放射性物質(zhì)發(fā)生泄漏巫湘。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,458評論 3 331
  • 文/蒙蒙 一昏鹃、第九天 我趴在偏房一處隱蔽的房頂上張望尚氛。 院中可真熱鬧,春花似錦洞渤、人聲如沸阅嘶。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽讯柔。三九已至,卻和暖如春护昧,著一層夾襖步出監(jiān)牢的瞬間魂迄,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評論 1 272
  • 我被黑心中介騙來泰國打工惋耙, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留捣炬,地道東北人。 一個月前我還...
    沈念sama閱讀 48,365評論 3 373
  • 正文 我出身青樓绽榛,卻偏偏與公主長得像湿酸,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子灭美,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,055評論 2 355