Android之Zygote启动详解

来源:互联网 发布:西安市旅游业数据 编辑:程序博客网 时间:2024/05/16 11:32

         我们知道Android系统是基于Linux内核的,在Linux系统中所有的进程都是init进程的子进程。Zygote也一样它是在系统启动的过程中由init进程创建的,在系统启动脚本init.rc中:

<span style="font-size:14px;">@init.rcservice zygote /syste/bin/app_process -Xzygote /system/bin -zygote --start-system-server            class main            socket zygote stream 666            onrestart restart surfaceflinger            ...</span>

        关键字server告诉init进程创建一个名为zygote的进程,执行的的程序是/syste/bin/app_process,后面都是传递给这个进程的参数。下面的socket表示这个zygote进行需要一个名称为zygote的socket套接字资源,系统启动后在/dev/socket目录下可以看到相关的文件。

 

        zygote 服务进程也叫孵化进程,在Linux的用户空间进程app_process会做一些zygote进程启动的前期工作,如启动runtime运行时的环境等,接着调用runtime.start()来执行zygote服务。runtime.start()这个函数实际是类函数AndroidRuntime::start(),会创建并启动一个虚拟机实例来执行com.android.internal.os.ZygoteInit这个包的main函数。这个main函数会fork一个子进程来启动systemServer,父进程就作为真正的孵化器存在了,每当系统要求执行一个Android应用程序,Zygote就会接收到socket消息fork出一个子进程来执行该应用程序。 而每一个Android应用程序都运行在一个Dalvik虚拟机实例里,每一个虚拟机实例都是一个独立的进程空间。

 

@frameworks/base/cmds/app_process/app_main.cpp

<span style="font-size:14px;">int main(int argc, char* argv[]){AppRuntime runtime;// 这里AppRuntime是AndroidRuntime的子类,启动runtime运行时环境。...// 获取参数/*argv[0] = "-Xzygote"argv[1] = "/system/bin"argv[2] = "--zygote"argv[3] = "--start-system-server"startSystemServer = true*/int i = runtime.addVMArguments(argc. argv);// 找到参数第一个不是以单个-开始的参数,这里是/system/binruntime.mParentDir = argv[i++]// 将目录保存到mParentDir变量中setArgsv0(argv0, "zygote")set_process_name("zygote");runtime.start("com.android.internal.os.zygoteInit", startSystemServer ? "start-system-server" : "");}</span>

        这里主要就是调用runtime.start() 函数,我们重点看下runtime类型为AppRuntime,它继承于AndroidRuntime类。

@frameworks/base/cmds/app_process/app_main.cpp

<span style="font-size:14px;">class AppRuntime : public AndroidRuntime{public:AppRuntime() : mParentDir(NULL), mClassName(NULL), mClass(NULL), mArgc(0), mArgv(NULL){}...const char* getClassName() const {}virtual void onVmCreated(JNIEnv* env) {}virtual void onStarted() {}virtual void onZygoteInit() {}virtual void onExit(int code)const char* mParentDir;const char* mClassName;jclass mClas;int mArgC;const char* const* mArgV;};</span>


 

<span style="font-size:14px;">@frameworks/base/include/android_runtime/AndroidRuntime.h@frameworks/base/core/jni/AndroidRuntime.cpp/* static */ JavaVM* AndroidRuntime::mJavaVM = NULL;void AndroidRuntime::start(const char* className, const char* options){...JNIEnv *env;startVm(&mJavaVM, &env);// start the virtual machineonVmCreated(env);startReg(env);// Register android functions // call className mainchar *slashClassName = toSlashClassName(className);jclass startClass = env->FindClass(slashClassName);jmethodID startMeth = env->GetStaticMethodID(startClass, "main", "([Ljava/lang/String;]V)");env->CallStaticVoidMethod(startClass, startMeth, strArray);free(slashClassName);...}</span>


         这个start()函数主要做三件事:一是调用startVM()启动虚拟机;二是调用startReg()注册JNI方法;三是调用com.android.internal.os.ZygoteInit类的main函数

 

1) startVM 启动虚拟机

 

2) startReg 注册JNI方法

 

3)启动com.android.internal.os.ZygoteInit的main函数

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

<span style="font-size:14px;">public static void main(String argv[]) {try {SamplingProfilerIntegration.start();registerZygoteSocket();// 注册socketpreloadClasses();// 加载资源preloadResources();SamplingProfilterIntegration.writeZygoteSnapshot();gc();if(argv[1].equals("start-system-server"))startSystemServer();// fork一个新的进程system_serverif(ZYGOTE_FORK_MODE)runForkMode();elserunSelectLoopMode();// Zygote进程进入无限循环,执行孵化工作closeServerSocket();} catch (MethodAndArgsCaller caller) {caller.run();}}</span>

 

       这里也是主要做三件事情:一是调用registerZygoteSocket函数创建了一个socket套接字用来和ActivityManagerService通信;二是调用startSystemServer函数启动SystemServer组件;三是调用runSelectLoopMode函数进程一个无限循环在前面创建的套接字socket上等待ActivityManagerService请求创建新的应用程序进程。
1)registerZygoteSocket

fork()创建子进程,父进程返回true。子进程执行RuntimeInit.zygoteInit。

@frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

<span style="font-size:14px;">public class ZygoteInit {...private static LocalServerSocket sServerSocket;private static final String ANDROID_SOCKET_ENV = "ANDROID_SOCKET_zygote";private static void registerZygoteSocket() {if(sServerSocket == NULL) {int fileDesc;String env = System.getenv(ANDROID_SOCKET_ENV);// 获取环境变量fileDesc = Integer.parseInt(env);sServerSocket = new LocalServerSocket(createFileDescriptor(fileDesc));}}}</span>

          

         这里通过System.getenv()获取环境变量ANDROID_SOCKET_ENV的值,通过这个文件描述符表示/dev/socket/zygote。那么这个环境变量又是谁设置的呢?在前面分析的解释执行系统启动脚本init.rc的init.c文件里面有个service_start()函数就是用来分析zygote并创建和设置相应socket的。

<span style="font-size:14px;">void service_start(struct service *svc, const char* dynamic_args) {...pid = fork();if ( pid == 0) {struct socketinfo *si;...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);publish_socket(si->name, s);}}...}#define ANDROID_SOCKET_ENV_PREFIX  "ANDROID_SOCKET_"#define ANDROID_SOCKET_DIR "/dev/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);// ANDROID_SOCKET_zygote = valfcntl(fd, F_SETFD, 0);}</span>


       这里每一个service命令都会使init进程调用fork函数创建一个新的进程来分析里面的socket选项,然后调用create_socket()函数在/dev/socket目录下创建一个设备文件,然后获得一个文件描述符并通过publish_socket()写入到环境变量中去。这样就把zygote这个socket的文件描述符写到ANDROID_SOCKET_zygote里面去了,这里创建socket文件描述符的create_socket()函数,最后通过调用execve(svc->args[0], (char**)arg_ptrs, (char**)ENV)去执行zygote的可执行程序,并将环境变量ENV参数传递过去了。所以ZygoteInit.registerZygoteSocket()函数就可以直接从环境变量中取出这个文件描述符来使用。如果其他进程需要打开这个/dev/socket/zygote 文件来和Zygote进程通信就需要通过文件名字连接LocalServerSocket。

2)startSystemServer

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

<span style="font-size:14px;">private static boolean startSystemServer() {String args[] = {"--setuid=1000", "--setgid=1000", "--setgroups=1001,1002,1003,1004,1005,1006...","--capabilities=13010432,130104352","--runtime-init","--nice-name=system_server","com.android.server.SystemServer",};ZygoteConnection.Arguments parsedArgs = null;parsedArgs = new ZygoteConnection.Arguments(args);ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);int pid = Zygote.forkSystemServer(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,parsedArgs.debugFlags, null, parsedArgs.permittedCapabilities,parsedArgs.effectiveCapabilities));if (pid == 0) {// 子进程handleSystemServerProcess(parsedArgs);}return true;// 父进程直接返回true}</span>

         这里Zygote进程通过调用Zygote.forkSystemServer()函数创建一个新的进程来启动SystemServer组件。

<span style="font-size:14px;">public class ZygoteInit {....private static void handleSystemServerProcess(ZygoteConnection.Arguments parsedArgs) {closeServerSocket();// 子进程不需要zygote套接字,直接关闭FileUtils.setUMask(FileUtils.S_IRWXG | FileUtils.S_IRWXO);...RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs);}}</span>
<span style="font-size:14px;">public class RuntimeInit {...public static final void zygoteInit(int targetSdkVersion, String[] argv) {redirectLogStreams();commonInit();zygoteInitNative();// 是一个native函数,主要完成Binder通信机制的初始化applicationInit(targetSdkVersion, argv);}public static final native void zygoteInitNative();private static void applicationInit(int targetSdkVersion, String[] argv) {VMRuntime.getRuntime().setTargetHeapUtilizatoin(0.75f);VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);final Arguments args;args = new Arguments(argv);invokeStaticMain(args.startClass, args.startArgs);}// 这个 className = "com.android.server.SystemServer"private static void invokeStaticMain(String className, String[] argv) {Class<?> cl;cl = Class.forName(className);Method m;m = cl.getMethod("main", new Class[] {String[].class});...throw new ZygoteInit.MethodAndArgsCaller(m, argv);}}</span>

 

       这个RuntimeInit.ZygoteInit()函数主要执行两个操作:一是调用zygoteInitNative来执行一个Binder进程间通信机制的初始化工作;二是调用com.android.server.SystemServer类的main函数。

(1) zygoteInitNative: 

<span style="font-size:14px;">@frameworks/base/core/jni/AndroidRuntime.cppstatic JNINativeMethod gMethods[] = {      ....     { "zygoteInitNative", "()V", (void*) com_android_internal_os_RuntimeInit_zygoteInit },     .... };static void com_android_internal_os_RuntimeInit_zygoteInit(JNIEnv* env, jobject clazz){       gCurRuntime->onZygoteInit();         // 就是启动Binder通信}</span>
<span style="font-size:14px;">virtual void onZygoteInit(){sp<ProcessState> proc = ProcessState::self();// 每个进程一份ProcessState对象,打开Binder驱动if(proc->supportsProcess()){proc->startThreadPool();// 启动一个线程用于Binder通信}}</span>


 

(2) SystemServer.main :

@frameworks/base/services/java/com/android/server/SystemServer.java

<span style="font-size:14px;">public class SystemServer {native public static void init1(Strig[] args);public static void main(String[] args) {....VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);System.loadLibrary("android_servers");init1(args);}public static final void init2() {Thread thr = new ServerThread();thr.setName("android.server.ServerThread");thr.start();}}<span style="color:#006600;">@frameworks/base/services/jni/com_android_server_SystemServer.cpp</span></span>
<span style="font-size:14px;">static void android_server_SystemServer_init1(JNIEnv* env, jobject clazz){system_init();}status_t system_init(){sp<ProcessState> proc(ProcessState::self());sp<IServiceManager> sm = defaultServiceManager();...AndroidRuntime* runtime = AndroidRuntime::getRuntime();JNIEnv* env = rungime->getJNIEnv();jclass clazz = env->FindClass("com/android/server/SystemServer");jmethodID methodId = env->GetStaticMethodID(clazz, "init2", "()V");env->CallStaticVoidMethod(clazz, methodId);ProcessState::self()->startThreadPool();IPCThreadState::self()->joinThreadPool();return NO_ERROR;}</span>


       这个SystemServer的main()函数首先会调用JNI方法init1,init1()会调用SystemServer的init2,在init2里面创建一个ServerThread线程执行一些系统关键服务的启动操作。

<span style="font-size:14px;">class ServerThread extends Thread {...public void run() {Looper.prepare();// Critical services ...ServiceManager.addService(Context.POWER_SERVICE, new PoperManagerService());ActivityManagerService.main();PackageManagerService.main(context);...}}</span>

        到现在为止,zygote已经fork()子进程完成了SystemServer组件的初始化启动操作,回到zygote.main()里面调用runSelectLoopMode()进入一个循环再前面创建的socket接口上等待ActivityManagerService请求创建新的应用程序。

3)runSelectLoopMode

 

<span style="font-size:14px;">public class ZygoteInit {....private static void runSelectLoopMode() throws MethodAndArgsCaller {ArrayList<FileDescriptor> fds = new ArrayList();ArrayList<ZygoteConnection> peers = new ArrayList();FileDescriptor[] fdArray = new FileDescriptor[4];fds.add(sServerSocket.getFileDescriptor());peers.add(NULL);int loopCount = GC_LOOP_COUNT;// 10while(true) {fdArray = fds.toArray(fdArray);index = selectReadble(fdArray);// 类似Linux下的select轮询,native 函数if(index < 0) {...} else if(index == 0) {// 表示有客户端连接上ZygoteConnection newPeer = acceptCommandPeer();peers.add(newPeer);fds.add(newPeer.getFileDescriptor());} else {// 客户端发送了请求过来,交给ZygoteConnection的runOnce()函数完成boolean done = peers.get(index).runOnce();if(done) {peers.remove(index);fds.remove(index);}}}}private static ZygoteConnection acceptCommandPeer() {...return new ZygoteConnection(sServerSocket.accept());}}</span>

 

        这里while(true)循环里面调用selectReadble(),这是一个native函数,类似select使用多路复用I/O模型。当返回0的时候表示有客户端连接上,ZygoteConnection表示Zygote的一个客户端,每当客户端连接上的时候acceptCommandPeer()返回一个ZygoteConnection对象,ZygoteConnection里面保存着accpet()返回的LocalSocket对象。然后将相应的文件描述符添加到fds里面,下次再对其调用selelct轮询。当返回值大于0的时候表示有客户端发过来的数据请求,交给ZygoteConnection对象的runOnce()函数处理。

        selectReadable()函数对应native函数为:com_android_internal_os_ZygoteInit_SelectReadable()

static jint com_android_internal_os_ZygoteInit_selectReadable (        JNIEnv *env, jobject clazz, jobjectArray fds){    if (fds == NULL) {        jniThrowNullPointerException(env, "fds == null");        return -1;    }    jsize length = env->GetArrayLength(fds);    fd_set fdset;    if (env->ExceptionOccurred() != NULL) {        return -1;    }    FD_ZERO(&fdset);    int nfds = 0;    for (jsize i = 0; i < length; i++) {        jobject fdObj = env->GetObjectArrayElement(fds, i);        if  (env->ExceptionOccurred() != NULL) {            return -1;        }        if (fdObj == NULL) {            continue;        }        int fd = jniGetFDFromFileDescriptor(env, fdObj);        if  (env->ExceptionOccurred() != NULL) {            return -1;        }        FD_SET(fd, &fdset);        if (fd >= nfds) {            nfds = fd + 1;        }    }    int err;    do {        err = select (nfds, &fdset, NULL, NULL, NULL);    } while (err < 0 && errno == EINTR);    if (err < 0) {        jniThrowIOException(env, errno);        return -1;    }    for (jsize i = 0; i < length; i++) {        jobject fdObj = env->GetObjectArrayElement(fds, i);        if  (env->ExceptionOccurred() != NULL) {            return -1;        }        if (fdObj == NULL) {            continue;        }        int fd = jniGetFDFromFileDescriptor(env, fdObj);        if  (env->ExceptionOccurred() != NULL) {            return -1;        }        if (FD_ISSET(fd, &fdset)) {            return (jint)i;        }    }    return -1;}

 

原创粉丝点击