国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

android源碼分析—Zygote和SystemServer啟動

RyanHoo / 1243人閱讀

摘要:注此次分析以源碼為例。孵化器受精卵名字是受精卵,其實就是幫助或其他進程啟動的一個玩意兒。啟動系統服務是系統的大核心之一,和一并重要,專管所有的系統服務。每個進程都走這一步這個分支到此先不往下跟蹤了,和啟動的過程關系不大了。

注:此次分析以6.0源碼為例。

android系統是從linux改過來的,因此這里從init進程開始進行分析。

init初始化過程

讓我們進入init.cpp來看看,首先看main:
/Volumes/aosp/WORKING_DIRECTORY/system/core/init/init.cpp

int main(int argc, char** argv) {
    // 判斷是否是啟動的第一階段,根據參數來判斷
    bool is_first_stage = (argc == 1) || (strcmp(argv[1], "--second-stage") != 0);
    
    if (is_first_stage) {
        // 如果是第一階段
        mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755");    // 掛載tmpfs文件系統(快速的臨時文件系統,建立在內存上,不可持久)
        mkdir("/dev/pts", 0755);
        mkdir("/dev/socket", 0755);
        mount("devpts", "/dev/pts", "devpts", 0, NULL); // 掛載devpts文件系統
        mount("proc", "/proc", "proc", 0, NULL);    // 掛載proc文件系統
        mount("sysfs", "/sys", "sysfs", 0, NULL);   // 掛載sysfs文件系統(設備結構)
    }
    
    ......
    
    if (!is_first_stage) {
        // Indicate that booting is in progress to background fw loaders, etc.
        close(open("/dev/.booting", O_WRONLY | O_CREAT | O_CLOEXEC, 0000));


        property_init();    // 初始化屬性域 system/core/init/Property_service.cpp

        // If arguments are passed both on the command line and in DT,
        // properties set in DT always have priority over the command-line ones.
        process_kernel_dt();
        process_kernel_cmdline();

        // Propogate the kernel variables to internal variables
        // used by init as well as the current required properties.
        export_kernel_boot_props();
    }
    
    ......
    
    if (is_first_stage) {
        if (restorecon("/init") == -1) {
            ERROR("restorecon failed: %s
", strerror(errno));
            security_failure();
        }
        
        // 重入main,進入第二階段
        char* path = argv[0];
        char* args[] = { path, const_cast("--second-stage"), nullptr };
        if (execv(path, args) == -1) {
            ERROR("execv("%s") failed: %s
", path, strerror(errno));
            security_failure();
        }
    }
    
    ......
    
    epoll_fd = epoll_create1(EPOLL_CLOEXEC);    // 創建epoll
    ......
    signal_handler_init();  // 初始化子進程處理器,防止僵尸進程。這里使用信號來監控子進程退出
    ......
    start_property_service();   // 啟動屬性服務
    init_parse_config_file("/init.rc"); // 解析init.rc文件
    ......
    // 不斷監聽執行上面rc解析出來的指令
    while (true) {
        if (!waiting_for_exec) {
            execute_one_command();  // 執行指令
            restart_processes();
        }

        int timeout = -1;
        if (process_needs_restart) {
            timeout = (process_needs_restart - gettime()) * 1000;
            if (timeout < 0)
                timeout = 0;
        }

        if (!action_queue_empty() || cur_action) {
            timeout = 0;
        }

        bootchart_sample(&timeout);

        epoll_event ev;
        int nr = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd, &ev, 1, timeout));
        if (nr == -1) {
            ERROR("epoll_wait failed: %s
", strerror(errno));
        } else if (nr == 1) {
            ((void (*)()) ev.data.ptr)();
        }
    }
}

整個init階段分為2個階段,第一階段主要是掛載文件系統等工作,然后這里會有個重入main的動作,這次重入后開始執行第二階段,第二階段主要處理各種屬性域,epoll,啟動屬性服務,防止僵尸進程等瑣碎的事情。然后開始執行init.rc中配置的指令。下面看看這個rc文件:

/Volumes/aosp/WORKING_DIRECTORY/system/core/rootdir/init.rc

import /init.environ.rc
import /init.usb.rc
import /init.${ro.hardware}.rc
import /init.usb.configfs.rc
import /init.${ro.zygote}.rc
import /init.trace.rc

可以看到這里引用了/init.${ro.zygote}.rc,對應的是類似init.zygote64.rc這些文件:

service zygote /system/bin/app_process64 -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
    writepid /dev/cpuset/foreground/tasks

這里實際執行的是app_main.cpp的main:
/Volumes/aosp/WORKING_DIRECTORY/frameworks/base/cmds/app_process/app_main.cpp

    // 根據參數設置類名
    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;
        }
    }
    ......
    if (zygote) {
        // 這里執行到ZygoteInit類中
        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.
");
        app_usage();
        LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
        return 10;
    }

根據參數判斷,如果是zygote則在后面執行runtime.start,給定的參數是ZygoteInit這個類。
runtime實際執行的是AndroidRuntime.cpp中的代碼:
/Volumes/aosp/WORKING_DIRECTORY/frameworks/base/core/jni

void AndroidRuntime::start(const char* className, const Vector& options, bool zygote)
    ......
    jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
            "([Ljava/lang/String;)V");
        if (startMeth == NULL) {
            ALOGE("JavaVM unable to find main() in "%s"
", className);
            /* keep going */
        } else {
            env->CallStaticVoidMethod(startClass, startMeth, strArray);

#if 0
            if (env->ExceptionCheck())
                threadExitUncaughtException(env);
#endif
        }
        ......
}

實際執行的就是env->CallStaticVoidMethod(startClass, startMeth, strArray);這句話,調用的就是ZygoteInit.java中的main。至此,從init進入到Zygote中了。

Zygote孵化器(受精卵)

zygote名字是受精卵,其實就是幫助app或其他進程啟動的一個玩意兒。內部就是走的fork分裂出一個進程來。

/Volumes/aosp/WORKING_DIRECTORY/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

public static void main(String argv[]) {
    try {
        ......
        for (int i = 1; i < argv.length; i++) {
            if ("start-system-server".equals(argv[i])) {    // 這里傳遞的就是這個
                startSystemServer = 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]);
            }
        }
        ......
        registerZygoteSocket(socketName);   // 注冊并啟動socket服務端,為zygote
        ......
        if (startSystemServer) {
            startSystemServer(abiList, socketName); // 啟動systemserver
        }
        ......
        runSelectLoop(abiList); // 進入looper,等待啟動app的請求
    } 
    // 注意這里,是個關鍵點。異常發生的時候調用了MethodAndArgsCaller這個runnable的run
    catch (MethodAndArgsCaller caller) {      
        caller.run();
    }
    
}

基本就這些了,總結一下:
1.zygote使用本地socket進行通訊,并接受請求從而進行分裂的處理;
2.啟動systemserver這個大戶;
3.zygote永不退出,生命周期在系統啟動一直到結束,并且從runSelectLoop開始徹底成為孵化器服務進程;
4.一旦發生MethodAndArgsCaller caller異常,調用MethodAndArgsCaller的call處理,后面我們會說到這個;

按照順序,我們首先來看看startSystemServer。

1. startSystemServer啟動系統服務

SystemServer是系統的2大核心之一,和Zygote一并重要,專管所有的系統服務。需要多帶帶開篇來闡述。這里我們只說啟動的過程。

private static boolean startSystemServer(String abiList, String socketName)
            throws MethodAndArgsCaller, RuntimeException {
    ......
    // fork SystemServer進程
    pid = Zygote.forkSystemServer(
        parsedArgs.uid, parsedArgs.gid,
        parsedArgs.gids,
        parsedArgs.debugFlags,
        null,
        parsedArgs.permittedCapabilities,
        parsedArgs.effectiveCapabilities);
    ......
    // 如果是子進程,就是SystemServer本身,執行
    if (pid == 0) {
        if (hasSecondZygote(abiList)) {
            waitForSecondaryZygote(socketName);
        }

        // 如果是子進程,即systemserver,調用handleSystemServerProcess進行后面的收尾工作
        handleSystemServerProcess(parsedArgs);
    }  
}

好吧,我們繼續看handleSystemServerProcess:

private static void handleSystemServerProcess(
            ZygoteConnection.Arguments parsedArgs)
            throws ZygoteInit.MethodAndArgsCaller {
......
RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
......
                
}

其實重要的就這一句話調用。繼續往下跟蹤:
/Volumes/aosp/WORKING_DIRECTORY/frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller {
    ......
    // 常規初始化,設置跟蹤,設置網絡代理
    commonInit();
    // AndroidRuntime.cpp c層函數
    nativeZygoteInit();
    // 應用程序初始化
    applicationInit(targetSdkVersion, argv, classLoader);
                
}

基本上就是上面這3個調用最重要,我們依次看下:
/Volumes/aosp/WORKING_DIRECTORY/frameworks/base/core/jni/AndroidRuntime.cpp

static void com_android_internal_os_RuntimeInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
    gCurRuntime->onZygoteInit();
}

看到了吧,回到了app_main.cpp AppRuntime的onZygoteInit中:

virtual void onZygoteInit()
{
    sp proc = ProcessState::self();
    ALOGV("App process: starting thread pool.
");
    // 啟動線程池,用于與binder通訊。每個進程都走這一步
    proc->startThreadPool();
}

這個分支到此先不往下跟蹤了,和啟動的過程關系不大了。
下面我們回到RuntimeInit.java看下applicationInit:

private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller {
        // 設置關閉引用程序是是否調用AppRuntime.onExit(),默認調用
        nativeSetExitWithoutCleanup(true);

        ......

        // 傳遞參數,并調用類的main方法
        invokeStaticMain(args.startClass, args.startArgs, classLoader);
    }

關鍵方法是invokeStaticMain,執行類的main方法,這個類在前面的startSystemServer里面有參數傳遞,具體是這樣的:

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",
            "--capabilities=" + capabilities + "," + capabilities,
            "--nice-name=system_server",
            "--runtime-args",
            "com.android.server.SystemServer",
        };

所以這個類就是SystemServer,調用的就是他的main方法。
下面看看invokeStaticMain內部:

private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
    throws ZygoteInit.MethodAndArgsCaller {
    Class cl;

    // 通過反射獲取類名
    try {
        cl = Class.forName(className, true, classLoader);
    } catch (ClassNotFoundException ex) {
        throw new RuntimeException(
                "Missing class when invoking static main " + className,
                ex);
    }

    // 獲取該類的main方法
    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);
    }

    /*
     * This throw gets caught in ZygoteInit.main(), which responds
     * by invoking the exception"s run() method. This arrangement
     * clears up all the stack frames that were required in setting
     * up the process.
     */
     // 拋出異常
    throw new ZygoteInit.MethodAndArgsCaller(m, argv);
}

看到這里一定會奇怪,為何在此處拋出一個異常:throw new ZygoteInit.MethodAndArgsCaller(m, argv);,這里我們需要往前回溯看看,到底在哪里捕獲的異常。結果是發現在ZygoteInit.java的main中進行的捕獲:

try {
    ......
    if (startSystemServer) {
        startSystemServer(abiList, socketName);
    }
    ......
} catch (MethodAndArgsCaller caller) {
     caller.run();
}

調用的起始也是從這里開始的,好吧,我們看看捕獲到異常之后做了什么。調用了caller.run()。拋出異常的時候已經new了一個throw new ZygoteInit.MethodAndArgsCaller(m, argv);這個對象了,并且參數給出的就是SystemServer類的main方法,那么繼續看ZygoteInit.MethodAndArgsCaller:

    public static class MethodAndArgsCaller extends Exception
            implements Runnable {
        /** method to call */
        private final Method mMethod;

        /** argument array */
        private final String[] mArgs;

        public MethodAndArgsCaller(Method method, String[] args) {
            mMethod = method;
            mArgs = args;
        }

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

run方法就是調用了一下這個方法,也就是調用了SystemServer的main方法,直接跳到main方法執行了。但是為何這么做呢?這里有個疑問。其實仔細想想也挺有意思。這一串調用從startSystemServer開始執行了比較深了,每次執行函數方法的時候都會伴隨著出現局部變量,那么就會直接開辟在棧上,之后的SystemServer又是個常駐不退出的進程,那么棧上面的這些空間也就意味著并不會釋放,而啟動過程只會執行一次,后面沒用了,這些東西沒有清理就一直存在。這里直接拋出異常后,在startSystemServer這個最初的位置捕獲,會導致異常發生后直接跳到捕獲的地方,之前所有的棧全部被清空。這下子明白了吧。google很聰明的利用了異常的做法回溯了棧,釋放不用的內存。真是非常聰明!

至此本文結束。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/67896.html

相關文章

  • App啟動流程

    摘要:孵化進程相當于是系統的根進程,后面所有的進程都是通過這個進程出來的雖然進程相當于系統的根進程,但是事實上它也是由系統的進程啟動的。 目錄介紹 1.什么是Zygote進程 1.1 簡單介紹 1.2 各個進程的先后順序 1.3 進程作用說明 2.Zygote進程的啟動流程 2.1 源碼位置 2.2 ZygoteInit類的main方法 2.3 registerZygoteSo...

    geekidentity 評論0 收藏0
  • android源碼分析-Zygote

    摘要:入口函數是創建確認是進程執行進程如果忽略掉參數這些細節,剩下的就是的建立和調用的方法了,啟動的是。下面再看下其實主要的就是這句話,前面的都是參數的配置。至此為止,的過程基本分析完畢。 android也是基于linux的系統,因此所有的進程都是從init進程開始的(直接或間接的從init進程fock出來的)。Zygote是受精卵進程,也是系統啟動過程中由init進程創建的,具體的看下啟動...

    zhunjiee 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<