源码分析-Zygote进程启动到Launcher

上两篇聊了Launcher之后的流程,现在咱们再看一下之前的流程 --- 也就是Zygote进程启动之后:


源码分析-Zygote进程启动到Launcher_第1张图片
无标题.png

Zygote, 意为“受精卵”,安卓进程孵化器
上图可以看出,由linux kernel 的 init (一生万物)进程可以启动Zygote进程,Zygote又启动dalvik,初始化java环境,app需要的资源,系统服务... fork(孵化)桌面Launcher以及各个app进程

在系统启动脚本system/core/rootdir/init.rc文件中,我们可以看到启动Zygote进程的脚本命令:

service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server  
    socket zygote stream 666   # zygote需要一个套接字
    onrestart write /sys/android_power/request_state wake  # zygote重启的话,需要执行这个操作
    onrestart write /sys/power/state on  
    onrestart restart media  
    onrestart restart netd  

app_process对应的源码在frameworks/base/cmds/app_process目录下,其入口函数main在文件app_main.cpp中:

/*
* 启动zygote的方式为/system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
* 所以 argc == 5
*      argv里头存的就是这5个参数argv[0]=="/system/bin/app_process" ,argv[1] == "-Xzygote"....
*/
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函数主要就是创建了runtime实例,并且解析参数,然后调用runtime的start函数,接着我们分析AppRuntime的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.
 */
 // 首先我们明确下传进来的参数  className == "com.android.internal.os.ZygoteInit"  options == "start-system-server"
void AndroidRuntime::start(const char* className, const char* options)
{
    ALOGD("\n>>>>>> AndroidRuntime START %s <<<<<<\n",
            className != NULL ? className : "(unknown)");

    /*
     * 'startSystemServer == true' means runtime is obsolete and not run from
     * init.rc anymore, so we print out the boot start event here.
     */
    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);  //配置ANDROID_ROOT环境变量
    }

    //const char* kernelHack = getenv("LD_ASSUME_KERNEL");
    //ALOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack);
    //1:调用startVm函数创建虚拟机;
    /* start the virtual machine */
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    JNIEnv* env;
    if (startVm(&mJavaVM, &env) != 0) { // 创建虚拟机
        return;
    }
    onVmCreated(env);
    //2:调用startReg函数注册Android Natvie函数;
    /*
     * Register android functions.
     */
    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.
     */
    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 {
            //3:让虚拟机去执行com.android.internal.os.ZygoteInit的main函数。
            /* 调用com.android.internal.os.ZygoteInit的main函数,strArray是参数,数组里面有两个元素,
            className == "com.android.internal.os.ZygoteInit"  options == "start-system-server" */
            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");
}

start函数主要做了以下几件事情:
1:调用startVm函数创建虚拟机;
2:调用startReg函数注册Android Natvie函数;
3:让虚拟机去执行com.android.internal.os.ZygoteInit的main函数。

public static void main(String argv[]) {
        try {
            // Start profiling the zygote initialization.
            SamplingProfilerIntegration.start();
            // 1、创建一个套接字,用于监听ams发过来的fork请求
            registerZygoteSocket(); 
            EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
                SystemClock.uptimeMillis());
            preload(); 
            // 2、加载classes 和resources, 后面会详细分析
            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.length != 2) {
                throw new RuntimeException(argv[0] + USAGE_STRING);
            }

            if (argv[1].equals("start-system-server")) {
                //3、 创建system server进程,ams wms pms等常见service都在该进程里面
                startSystemServer(); 
            } else if (!argv[1].equals("")) {
                throw new RuntimeException(argv[0] + USAGE_STRING);
            }

            Log.i(TAG, "Accepting command socket connections");

            if (ZYGOTE_FORK_MODE) {
                runForkMode();
            } else {
                // 4、进入循环监听模式,监听外来请求
                runSelectLoopMode(); 
            }

            closeServerSocket();
        } catch (MethodAndArgsCaller caller) {
            caller.run();
        } catch (RuntimeException ex) {
            Log.e(TAG, "Zygote died with exception", ex);
            closeServerSocket();
            throw ex;
        }
    }

com.android.internal.os.ZygoteInit的main函数主要做了四件事情:

1:调用registerZygoteSocket()创建一个套接字,用于监听ams发过来的fork请求,如下:
private static void registerZygoteSocket(String socketName) {
    if (sServerSocket == null) {
        int fileDesc;
        //此处的socket name,就是zygote
        final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
        try {
            //记得么?在init.zygote.rc被加载时,就会创建一个名为zygote的socket
            String env = System.getenv(fullSocketName);
            fileDesc = Integer.parseInt(env);
        } catch (RuntimeException ex) {
            throw new RuntimeException(fullSocketName + " unset or invalid", ex);
        }

        try {
            FileDescriptor fd = new FileDescriptor();
            //获取zygote socket的文件描述符
            fd.setInt$(fileDesc);
            //将zygote socket包装成一个server socket
            sServerSocket = new LocalServerSocket(fd);
        } catch (IOException ex) {
            throw new RuntimeException("Error binding to local socket '" + fileDesc + "'", ex);
        }
    }
}

2:调用preload()预加载classes 和resources,如下;

static void preload() {
    Log.d(TAG, "begin preload");
    //读取文件framework/base/preloaded-classes,然后通过反射加载对应的类
    //需要加载数千个类,启动慢的原因之一
    preloadClasses();
    //负载加载一些常用的系统资源
    preloadResources();
    //图形相关的
    preloadOpenGL();
    //一些必要库
    preloadSharedLibraries();
    //好像是语言相关的字符信息
    preloadTextResources();
    // Ask the WebViewFactory to do any initialization that must run in the zygote process, for memory sharing purposes.
    WebViewFactory.prepareWebViewInZygote();
    Log.d(TAG, "end preload");
}

3:调用startSystemServer()创建system server进程,ams wms pms等常见service都在该进程里面,如下;

private static boolean startSystemServer(String abiList, String socketName) {
    //准备capabilities参数
    ........
    String args[] = {
        "--setuid=1000",
        "--setgid=1000",
        "--setgroups=.........",
        "--capabilities=" + capabilities + "," + capabilities,
        "--nice-name=system_server",
        "--runtime-args",
        "com.android.server.SystemServer",
    };
    ZygoteConnection.Arguments parsedArgs = null;

    int pid;

    try {
        //将上面准备的参数,按照ZygoteConnection的风格进行封装
        parsedArgs = new ZygoteConnection.Arguments(args);
        ...........

        //通过fork"分裂"出system server
        /* 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) {
        throw new RuntimeException(ex);
    }

    if (pid == 0) {
        ............
        //pid = 0, 在进程system server中
        //system server进程处理自己的工作
        handleSystemServerProcess(parsedArgs);
    }

    return true;
}

4:调用runSelectLoopMode()进入循环监听模式,监听外来请求,如下。

private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
    ArrayList fds = new ArrayList();
    ArrayList peers = new ArrayList();

    //首先将server socket加入到fds
    fds.add(sServerSocket.getFileDescriptor());
    peers.add(null);

    while (true) {
        StructPollfd[] pollFds = new StructPollfd[fds.size()];
        for (int i = 0; i < pollFds.length; ++i) {
            pollFds[i] = new StructPollfd();
            pollFds[i].fd = fds.get(i);
            //关注事件到来
            pollFds[i].events = (short) POLLIN;
        }
        try {
            //等待事件到来
            Os.poll(pollFds, -1);
        } catch (ErrnoException ex) {
            throw new RuntimeException("poll failed", ex);
        }
        //注意这里是倒序的
        for (int i = pollFds.length - 1; i >= 0; --i) {
            if ((pollFds[i].revents & POLLIN) == 0) {
                continue;
            }
            //server socket最先加入fds, 因此这里是server socket收到数据
            if (i == 0) {
                //收到新的建立通信的请求,建立通信连接
                ZygoteConnection newPeer = acceptCommandPeer(abiList);
                //加入到peers和fds
                peers.add(newPeer);
                fds.add(newPeer.getFileDesciptor());
             } else {
                //其它通信连接收到数据,runOnce执行对应命令
                boolean done = peers.get(i).runOnce();
                if (done) {
                    //对应通信连接不再需要执行其它命令,关闭并移除
                    peers.remove(i);
                    fds.remove(i);
                }
            }
        }
    }
}

从上面代码可知,初始时,fds中仅有server socket,因此当有数据到来时,将执行i ==0 的部分。
此时,显然是需要创建新的通信连接,因此acceptCommandPeer将被调用。

private static ZygoteConnection acceptCommandPeer(String abiList) {
    try {
        return new ZygoteConnection(sServerSocket.accept(), abiList);
    } catch (IOException ex) {
        throw new RuntimeException("IOException during accept()", ex);
    }
}
总结
1:acceptCommandPeer封装了socket的accpet函数。于是我们知道,对应的新的连接,zygote将会创建出一个新的socket与其通信,并将该socket加入到fds中。因此,一旦通信连接建立后,fds中将会包含有多个socket。
2:当poll监听到这一组sockets上有数据到来时,就会从阻塞中恢复。于是,我们需要判断到底是哪个socket收到了数据。
3:在runSelectLoop中采用倒序的方式轮询,由于server socket第一个被加入到fds,因此最后轮询到的socket才需要处理新建连接的操作;其它socket收到数据时,仅需要调用zygoteConnection的runonce函数执行数据对应的操作。
4:若一个连接处理完所有对应消息后,该连接对应的socket和连接等将被移除。

那么从 system server 到 ActivityManager 到 Launcher 又是如何沟通的呢,也就是第一篇提到的
AMS.startProcessLocked()-->Process.start()-->zygoteSendArgsAndGetResult()-->ZygoteInit.invokeStaticMain(cloader, className, mainArgs)(ActivityThread.main)
system server,具体的过程在介绍system server时再分析

你可能感兴趣的:(源码分析-Zygote进程启动到Launcher)