学习Android系统(kitkat)进程Zygote启动过程

本文部分内容参考罗升阳的博客(源代码为kitkat4.4版本,会有一些不同,特别是后面第8步开始有较大的不同),在此表示感谢,出处链接:http://blog.csdn.net/luoshengyang/article/details/6768304

安卓系统中所有的应用程序进程和系统服务进程SystemService都是由Zygote进程fork出来的,因此就先从源码级别来看看Zygote进程的启动过程。而Linux中所有的进程都由init进程创建,而Zygote也不例外,所以在系统的bootable\diskinstaller\init.rc文件中肯定有Zygote进程的启动代码,如下:

    service zygote /system/bcorein/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

第一行表示了启动名为zygote的进程,进程要执行的程序为/system/bcorein/app_process,而后面则是需要执行的参数;第二行指定了这个进程所属的类别,此处指定了main,在/system/core/init/ReadMe.txt中的定义如下,表示同一个类别的服务会同时启动或停止,关于init.rc中的启动脚本的格式说明都在这个文档里:

**class <name> Specify a class name for the service.  All services in a
   named class may be started or stopped together.  A service
   is in the class "default" if one is not specified via the
   class option.**

第三行则是创建一个名为zygote的socket资源,要启动应用程序时ActivityManagerService就是通过这个socket给zygote进程发送fork请求的,后面的一些onrestart开头的指令则是服务在重启的时候需要执行的。启动脚本就分析的差不多了,下面便是分析app_process,源代码在frameworks/base/cmds/app_process/app_main.cpp文件中,入口函数为main函数。整个执行过程的序列图如下:


1.app_process.main

首先来看app_process中的main代码,这段代码在frameworks\base\cmds\app_process\App_main.cpp中:

    int main(int argc, char* const argv[])
    {
    //最开始的一部分是针对arm平台的特殊处理,大意是说:暂时恢复到兼容的内存布局,以避免破坏第三方应用程序,在将来的安卓版本会被去掉;还提到了这个会破坏一些程序引入的过期的安卓链接器。具体什么意思还没搞明白。
    #ifdef __arm__
        /*
         * b/7188322 - Temporarily revert to the compat memory layout
         * to avoid breaking third party apps.
         *
         * THIS WILL GO AWAY IN A FUTURE ANDROID RELEASE.
         *
         * http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=7dbaa466
         * changes the kernel mapping from bottom up to top-down.
         * This breaks some programs which improperly embed
         * an out of date copy of Android's linker.
         */
        char value[PROPERTY_VALUE_MAX];
        property_get("ro.kernel.qemu", value, "");
        bool is_qemu = (strcmp(value, "1") == 0);
        //下面的代码则是获得"ro.kernel.qemu"的值不为1没有“NO_ADDR_COMPAT_LAYOUT_FIXUP”这个环境变量,则添加这个环境变量值为1,且重新执行这个main函数
        if ((getenv("NO_ADDR_COMPAT_LAYOUT_FIXUP") == NULL) && !is_qemu) {
            //#define personality(pers) (pers & PER_MASK)
            int current = personality(0xFFFFFFFF);
            if ((current & ADDR_COMPAT_LAYOUT) == 0) {
                personality(current | ADDR_COMPAT_LAYOUT);
                setenv("NO_ADDR_COMPAT_LAYOUT_FIXUP", "1", 1);
                execv("/system/bin/app_process", argv);
                return -1;
            }
        }
        //删除这个环境变量
        unsetenv("NO_ADDR_COMPAT_LAYOUT_FIXUP");
    #endif
        //根据参数设置两个全局变量
        // These are global variables in ProcessState.cpp
        mArgC = argc;
        mArgV = argv;

        mArgLen = 0;
        for (int i=0; i<argc; i++) {
            mArgLen += strlen(argv[i]) + 1;
        }
        mArgLen--;

        //AppRuntime继承自AndroidRuntime
        AppRuntime runtime;
        const char* argv0 = argv[0];

        // Process command line arguments
        // ignore argv[0]
        argc--;
        argv++;

        // Everything up to '--' or first non '-' arg goes to the vm
        //这里会添加-Xzygote这个参数且返回1
        int i = runtime.addVmArguments(argc, argv);

        // Parse runtime arguments.  Stop at first unrecognized option.
        bool zygote = false;
        bool startSystemServer = false;
        bool application = false;
        const char* parentDir = NULL;
        const char* niceName = NULL;
        const char* className = NULL;
        while (i < argc) {
            const char* arg = argv[i++];
            if (!parentDir) {//第一轮循环设置父目录为/system/bin
                parentDir = arg;
            } else if (strcmp(arg, "--zygote") == 0) {//第二轮循环执行的代码
                zygote = true;
                niceName = "zygote";
            } 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 = arg + 12;
            } else {
                className = arg;
                break;
            }
        }

        if (niceName && *niceName) {
            setArgv0(argv0, niceName);
            set_process_name(niceName);
        }

        runtime.mParentDir = parentDir;

        //由于上面zygote已经被设置为true,因此会执行ZygoteInit,而第二个参数则是"start-system-server"
        if (zygote) {
            runtime.start("com.android.internal.os.ZygoteInit",
                    startSystemServer ? "start-system-server" : "");
        } else if (className) {
            // Remainder of args get passed to startup class main()
            runtime.mClassName = className;
            runtime.mArgC = argc - i;
            runtime.mArgV = argv + i;
            runtime.start("com.android.internal.os.RuntimeInit",
                    application ? "application" : "tool");
        } 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;
        }

还有两点需要注意的地方,首先是在AppRuntime初始化的时候会调用其父类的构造函数,代码如下所示:

    AndroidRuntime::AndroidRuntime() :
            mExitWithoutCleanup(false)
    {
        ...

        assert(gCurRuntime == NULL);        // one per process
        gCurRuntime = this;
    }

在构造函数的最后,其会判断全局变量gCurRuntime是否已经被赋值,如果没有则将当前对象赋值给他,这样其他地方需要这个对象的指针就可以通过下面这个函数来获得:

AndroidRuntime* AndroidRuntime::getRuntime()
{
    return gCurRuntime;
}

第二点,上面的在运行start函数之前先调用AndroidRuntime类中的addVMArguments函数,功能是往全局变量mOptions中添加虚拟机启动的参数(目前理解是这样的)并返回添加成功的参数个数,这里会把参数-Xzygote添加进去:

int AndroidRuntime::addVmArguments(int argc, const char* const argv[])
{
    int i;

    for (i = 0; i<argc; i++) {
        if (argv[i][0] != '-') {
            return i;
        }
        if (argv[i][1] == '-' && argv[i][2] == 0) {
            return i+1;
        }

        JavaVMOption opt;
        memset(&opt, 0, sizeof(opt));
        opt.optionString = (char*)argv[i];
        mOptions.add(opt);
    }
    return i;
}

总的来说,app_main函数就是创建一个AppRuntime对象,然后设置各种启动参数,最终调用从AndroidRuntime继承过来的satrt的函数做进一步的处理。

2.AndroidRuntime.start

由于AppRuntime中没有start函数,所以这里调用的必然是AndroidRuntime种的start函数,代码在frameworks\base\core\jni\AndroidRuntime.cpp中,这里其实还有一段注释,大意是说这个start函数会启动传入的className的静态main函数,而第二个参数则是main函数的参数:

void AndroidRuntime::start(const char* className, const char* options)
{
    ...

    /* start the virtual machine */
    //初始化JniInvocation对象
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    JNIEnv* env;
    //启动虚拟机,首先在startVm中根据大量的系统属性和定义来指定一些参数,随后调用JniInvocation的JNI_CreateJavaVM函数来进行启动dalvik虚拟机,而后在JNI_CreateJavaVM函数中再调用dvmStartup进行启动,最后在函数调用各种函数来完成
    if (startVm(&mJavaVM, &env) != 0) {
        return;
    }
    //这个函数只有一行注释:If AndroidRuntime had anything to do here, we'd have done it in 'start'.
    onVmCreated(env);

    /* Register android functions. */
    //startReg会调用register_jni_procs注册JNI方法
    if (startReg(env) < 0) {
        ALOGE("Unable to register all android natives\n");
        return;
    }

    /*
     * We want to call main() with a String array with arguments in it.
     * At present we have two arguments, the class name and an option string.
     * Create an array to hold them.
     */
    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.
     */
    //把com.android.internal.os.ZygoteInit中的.换成/,随后找到这个类的main函数并调用。当前线程成为虚拟机的主线程,直到虚拟机退出了才会返回
    char* slashClassName = toSlashClassName(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);

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

    ALOGD("Shutting down VM\n");
    if (mJavaVM->DetachCurrentThread() != JNI_OK)
        ALOGW("Warning: unable to detach main thread\n");
    if (mJavaVM->DestroyJavaVM() != 0)
        ALOGW("Warning: VM did not shut down cleanly\n");
}

还需要注意以下几点,首先注册的jni方法非常多,比如:



第二点就是变量env其实是JNINativeInterface对象的指针,其调用的函数都无法找到源代码,只能找到定义的接口,所以目前无法看其详细的实现。

3.ZygoteInit.main

ZygoteInit已经是Java代码了,这个类在frameworks\base\core\java\com\android\internal\os\ZygoteInit.java源文件中,这个类的说明如下,大意就是说这个类是用来启动zygote进程并初始化一些类的,然后等待一个socket信号,他就会fork处带有初始状态的虚拟机的子进程:

/**
 * 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.
 *
 * Please see {@link ZygoteConnection.Arguments} for documentation on the
 * client protocol.
 *
 * @hide
 */

该类中main函数的代码如下:

    public static void main(String argv[]) {
        ... ...

        //注册sockets,首先获取系统的socket环境变量,而后创建文件描述符,最后创建服务器端socket,监听socket信号
        registerZygoteSocket();

        ... ...

        //如果参数正确则启动SystemServer()
        if (argv[1].equals("start-system-server")) {
            startSystemServer();
        } else if (!argv[1].equals("")) {
            throw new RuntimeException(argv[0] + USAGE_STRING);
        }

        //这个函数是一个while循环,一直等待接收socket连接并处理
        runSelectLoop();

        closeServerSocket();

        ... ...
    }

4.ZygoteInit.registerZygoteSocket

这个函数主要是创建新的socket服务端套接字,代码如下:

    private static void registerZygoteSocket() {
        if (sServerSocket == null) {
            int fileDesc;
            try {
                //获取socket环境变量
                String env = System.getenv(ANDROID_SOCKET_ENV);
                fileDesc = Integer.parseInt(env);
            } catch (RuntimeException ex) {
                throw new RuntimeException(
                        ANDROID_SOCKET_ENV + " unset or invalid", ex);
            }

            try {
                //创建文件描述符然后创建服务端套接字
                sServerSocket = new LocalServerSocket(
                        createFileDescriptor(fileDesc));
            } catch (IOException ex) {
                throw new RuntimeException(
                        "Error binding to local socket '" + fileDesc + "'", ex);
            }
        }
    }

ANDROID_SOCKET_ENV的定义如下:

    private static final String ANDROID_SOCKET_ENV = "ANDROID_SOCKET_zygote";

但是为何仅仅通过'ANDROID_SOCKET_zygote'这个字符串就能够获得socket环境变量呢?原来在init进程解释执行init.rc中启动service的代码时都会调用service_start函数,而这个函数中会根据init.rc中socket的描述来创建service的socket,有如下代码:

    void service_start(struct service *svc, const char *dynamic_args)
    {
        ... ...
        pid = fork();

        if (pid == 0) {
            struct socketinfo *si;
            struct svcenvinfo *ei;
            ... ...
            //从传入的svc中获得sockets参数并创建socket
            for (si = svc->sockets; si; si = si->next) {
                int socket_type = (
                        !strcmp(si->type, "stream") ? SOCK_STREAM :
                            (!strcmp(si->type, "dgram") ? SOCK_DGRAM : SOCK_SEQPACKET));
                int s = create_socket(si->name, socket_type,
                                      si->perm, si->uid, si->gid);
                if (s >= 0) {
                    //添加到环境变量中
                    publish_socket(si->name, s);
                }
            }
    }

其中publish_socket函数非常关键,代码如下:

static void publish_socket(const char *name, int fd)
{
    char key[64] = ANDROID_SOCKET_ENV_PREFIX;
    char val[64];

    strlcpy(key + sizeof(ANDROID_SOCKET_ENV_PREFIX) - 1,
            name,
            sizeof(key) - sizeof(ANDROID_SOCKET_ENV_PREFIX));
    snprintf(val, sizeof(val), "%d", fd);
    //添加到环境变量
    add_environment(key, val);

    /* make sure we don't close-on-exec */
    fcntl(fd, F_SETFD, 0);
}

而这里传进来的name变量便是字符串"zygote",ANDROID_SOCKET_ENV_PREFIX的宏定义如下:

#define ANDROID_SOCKET_ENV_PREFIX    "ANDROID_SOCKET_"

这样,"ANDROID_SOCKET_zygote"这个字符串便作为/dev/sockets/zygote这个socket的文件描述符的key,这样就能从环境变量就有zygote的socket了。与此同时这里的执行create_socket函数和ZygoteInit.registerZygoteSocket是在同一个进程中,所以能够直接通过字符串获得socket,但是如果其他进程需要获得这个socket,那就需要通过打开socket文件来进行通信了。

5.ZygoteInit.startSystemServer()

这个函数是用来启动SystemServer这个进程的,代码如下:

    private static boolean startSystemServer()
            throws MethodAndArgsCaller, RuntimeException {
        ... ...
        /* Hardcoded command line to start the system server */
        //这些是启动SystemServer进程的参数
        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);
            ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
            ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);

            /* Request to fork the system server process */
            //fork出一个子进程以启动SystemServer
            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 */
        //如果返回的pid为0则会执行handleSystemServerProcess函数,注意这里是SystemServer进程执行这个函数,而不是Zygote这个进程
        if (pid == 0) {
            handleSystemServerProcess(parsedArgs);
        }

        return true;
    }

6.ZygoteInit.handleSystemServerProcess

这个函数首先会关闭掉从父进程继承socket,因为他用不到这些socket。随后则会调用Runtime.Init函数进行进一步的操作:

    private static void handleSystemServerProcess(
            ZygoteConnection.Arguments parsedArgs)
            throws ZygoteInit.MethodAndArgsCaller {

        closeServerSocket();

        // 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.
             */
            RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs);
        }

        /* should never reach here */
    }

7.RuntimeInit.zygoteInit

这个类在frameworks\base\core\java\com\android\internal\os\RuntimeInit.java这个文件中,代码如下:

    public static final void zygoteInit(int targetSdkVersion, String[] argv)
            throws ZygoteInit.MethodAndArgsCaller {
        if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");
        //重定向"System.out"和"System.err"到Android Log
        redirectLogStreams();
        //用于初始化诸如:默认异常处理、时区、日志、Http代理、流量、调试跟踪信息等各种设置
        commonInit();
        //没找到代码,猜测可能是zygote的初始化函数
        nativeZygoteInit();

        applicationInit(targetSdkVersion, argv);
    }

这个函数进行一系列的初始化等操作后调用同一个类中的applicationInit函数继续处理。

8.RuntimeInit.applicationInit

这个函数主要就是通过invokeStaticMain函数来调用在参数中的class的main函数,而这个class正是SystemServer

    private static void applicationInit(int targetSdkVersion, String[] argv)
            throws ZygoteInit.MethodAndArgsCaller {
        ... ...

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

9.SystemServer.main

这个类在frameworks\base\services\java\com\android\server\SystemServer.java这个文件中,代码如下:

    public static void main(String[] args) {

       //前面的代码主要就是加载一些库以及做一些设置而已
        ... ...
        // Initialize native services.
        //初始化一些服务,具体的代码暂时没找到,等找到了补上
        nativeInit();

        // 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();
        //这个会调用ServerThread的initAndLoop函数
        thr.initAndLoop();
    }
}

10.SystemThread.initAndLoop

这个函数非常大,主要用于启动一些非常关键的系统服务以及循环的给zygote发送socket请求以运行应用程序。鉴于函数比较大,所以下面将分块讲解功能以便于理解。

10.1 创建消息循环队列

首先会创建一个Looper,等到所有的初始化任务完成之后在启动这个循环:

    public void initAndLoop() {

        Looper.prepareMainLooper();
        ... ...

        //最后
        Looper.loop();
        Slog.d(TAG, "System ServerThread is exiting!");
    }

10.2 各种服务变量的定义

从下面这些变量的定义可以看到这个函数将会初始化这个服务,这些服务都是间接继承自Binder这个类,因此说是Binder服务更为恰当,至于什么是Binder,可以参考http://www.cnblogs.com/linucos/archive/2012/05/24/2516623.html:

    public void initAndLoop() {
        ... ...
        Installer installer = null;
        AccountManagerService accountManager = null;
        ContentService contentService = null;
        LightsService lights = null;
        PowerManagerService power = null;
        DisplayManagerService display = null;
        BatteryService battery = null;
        VibratorService vibrator = null;
        AlarmManagerService alarm = null;
        MountService mountService = null;
        NetworkManagementService networkManagement = null;
        NetworkStatsService networkStats = null;
        NetworkPolicyManagerService networkPolicy = null;
        ConnectivityService connectivity = null;
        WifiP2pService wifiP2p = null;
        WifiService wifi = null;
        NsdService serviceDiscovery= null;
        IPackageManager pm = null;
        Context context = null;
        WindowManagerService wm = null;
        BluetoothManagerService bluetooth = null;
        DockObserver dock = null;
        UsbService usb = null;
        SerialService serial = null;
        TwilightService twilight = null;
        UiModeManagerService uiMode = null;
        RecognitionManagerService recognition = null;
        NetworkTimeUpdateService networkTimeUpdater = null;
        CommonTimeManagementService commonTimeMgmtService = null;
        InputManagerService inputManager = null;
        TelephonyRegistry telephonyRegistry = null;
        ConsumerIrService consumerIr = null;
        DevicePolicyManagerService devicePolicy = null;
        StatusBarManagerService statusBar = null;
        InputMethodManagerService imm = null;
        AppWidgetService appWidget = null;
        NotificationManagerService notification = null;
        WallpaperManagerService wallpaper = null;
        LocationManagerService location = null;
        CountryDetectorService countryDetector = null;
        TextServicesManagerService tsms = null;
        LockSettingsService lockSettings = null;
        DreamManagerService dreamy = null;
        AssetAtlasService atlas = null;
        PrintManagerService printManager = null;
        ... ...
    }

10.3 各个服务的创建

部分创建上面定义的Binder服务的代码:

    public void initAndLoop() {
        ... ...
        // bootstrap services,引导服务的创建
        Slog.i(TAG, "Waiting for installd to be ready.");
        installer = new Installer();
        installer.ping();

        Slog.i(TAG, "Power Manager");
        power = new PowerManagerService();
        ServiceManager.addService(Context.POWER_SERVICE, power);

        Slog.i(TAG, "Activity Manager");
        context = ActivityManagerService.main(factoryTest);

        //其他服务,鉴于服务太多,其他服务的创建就不一一列出了
        Slog.i(TAG, "Display Manager");
        display = new DisplayManagerService(context, wmHandler);
        ServiceManager.addService(Context.DISPLAY_SERVICE, display, true);

        Slog.i(TAG, "Telephony Registry");
        telephonyRegistry = new TelephonyRegistry(context);
        ServiceManager.addService("telephony.registry", telephonyRegistry);

        Slog.i(TAG, "Scheduling Policy");
        ServiceManager.addService("scheduling_policy", new SchedulingPolicyService());
        ... ...
    }

10.4 测试服务是否正确启动

下面是部分测试的代码:

    public void initAndLoop() {
        ... ...
        try{
            ActivityManagerService.self().startObservingNativeCrashes();
        } catch (Throwable e) {
            reportWtf("observing native crashes", e);
        }
        if (!headless) {
            startSystemUi(contextF);
        }
        try {
            if (mountServiceF != null) mountServiceF.systemReady();
        } catch (Throwable e) {
            reportWtf("making Mount Service ready", e);
        }
        try {
            if (batteryF != null) batteryF.systemReady();
        } catch (Throwable e) {
            reportWtf("making Battery Service ready", e);
        }
        try {
            if (networkManagementF != null) networkManagementF.systemReady();
        } catch (Throwable e) {
            reportWtf("making Network Managment Service ready", e);
        }
        ... ...
    }

这样initAndLoop函数就执行完了,现在一直回溯直到第三步。

11.ZygoteInit.runSelectLoop

现在又回到了ZygoteInit的main函数中,接下去执行的是runSelectLoop函数,这个函数运行一个while循环来接受SystemServer进程发送过来的fork子进程的消息:

    private static void runSelectLoop() throws MethodAndArgsCaller {
        ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
        ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
        FileDescriptor[] fdArray = new FileDescriptor[4];

        //把几个socket文件描述符放入fds数组中
        fds.add(sServerSocket.getFileDescriptor());
        peers.add(null);

        int loopCount = GC_LOOP_COUNT;
        while (true) {
            int index;

            try {
                fdArray = fds.toArray(fdArray);
                //返回可读的socket的在数组中的索引
                index = selectReadable(fdArray);
            } catch (IOException ex) {
                throw new RuntimeException("Error in select()", ex);
            }

            if (index < 0) {
                throw new RuntimeException("Error in select()");
            } else if (index == 0) {
                ZygoteConnection newPeer = acceptCommandPeer();
                peers.add(newPeer);
                fds.add(newPeer.getFileDesciptor());
            } else {
                boolean done;
                //runOnce用来fork子进程
                done = peers.get(index).runOnce();

                if (done) {
                    peers.remove(index);
                    fds.remove(index);
                }
            }
        }
    }

总的来说,Zygote进程的启动过程基本上分析的差不多了,当然还有少部分函数由于暂时找不到源码位置尚未分析。主要的流程是:
1.设置参数,启动虚拟机,调用Zygote的main函数
2.注册Zygote的socket套接字,fork SystemServer进程并使子进程执行指定函数
3.开启各种Binder服务,开启接收消息的循环队列
4.Zygote开始不断尝试从socket读取指令以便启动新的应用程序

这是学习安卓源代码系列第一篇,学习前人的经验,结合自己的实践学习一些东西,希望自己有所收获,进步地更快吧。后面要加快更新进度!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值