Android Zygote进程(一)

简介: 学习笔记

Init进程启动后,最重要的一个进程就是Zygote进程,Zygote是所有应用的鼻祖。SystemServer和其他所有Dalivik虚拟机进程都是由Zygote fork而来。

Zygote进程由app_process启动,Zygote是一个C/S模型,Zygote进程作为服务端,其他进程作为客户端向它发出“孵化-fork”请求,而Zygote接收到这个请求后就“孵化-fork”出一个新的进程。

由于Zygote进程在启动时会创建Java虚拟机,因此通过fork而创建的应用程序进程和SystemServer进程可以在内部获取一个Java虚拟机的实例拷贝。

架构图


Zygote是image.png如何启动的

Init进程启动后,会解析init.rc文件,然后创建和加载service字段指定的进程。zygote进程就是以这种方式,被init进程加载的。

/system/core/rootdir/init.rc

import /system/etc/init/hw/init.${ro.zygote}.rc

其中${ro.zygote} 由各个厂家使用,现在的主流厂家基本使用zygote64_32,因此,我们的rc文件为 init.zygote64_32.r。它会启动两个zygote进程(名为zygote和zygote——secondary),对应的执行程序分别是app_prcocess64(主模式)、app_process32。

init.zygote64_32.rc

/android/system/core/rootdir/init.zygote64_32.rc

service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote

    classmain

    priority -20

    user root //用户为root

    group root readproc reserved_disk //访问组支持root readproc reserved_disk

    socket zygote stream 660 root system//创建一个socket,名字叫zygote,以tcp形式,可以在/dev/socket 中看到一个 zygote的socket

    socket usap_pool_primary stream 660 root system

    onrestart exec_background - systemsystem-- /system/bin/vdc volume abort_fuse

    onrestart write /sys/power/state on

     onrestart restart audioserver

     onrestart restart cameraserver

     onrestart restart media

     onrestart restart netd

     onrestart restart wificond

     task_profiles ProcessCapacityHigh MaxPerformance

     critical window=${zygote.critical_window.minute:-off} target=zygote-fatal

 

 service zygote_secondary /system/bin/app_process32 -Xzygote /system/bin --zygote --socket-name=zygote_secondary --enable-lazy-preload

     classmain

     priority -20

     user root

     group root readproc reserved_disk

     socket zygote_secondary stream 660 root system

     socket usap_pool_secondary stream 660 root system

     onrestart restart zygote

     task_profiles ProcessCapacityHigh MaxPerformance

从上面一段代码可以看出:

第一个Zygote进程:

进程名:zygote

进程通过 /system/bin/app_process64来启动

启动参数: -Xzygote

/system/bin

--zygote

--start-system-server

--socket-name=zygote

socket的名称:zygote

第二个Zygote进程:

进程名:zygote_secondary

进程通过 /system/bin/app_process32来启动

启动参数: -Xzygote

/system/bin

--zygote

--socket-name=zygote_secondary

--enable-lazy-preload

socket的名称:zygote_secondary

对应的代码入口为:/android/frameworks/base/cmds/app_process/app_main.cpp

Zygote启动后做了什么

init进程通过init.zygote64_32.rc来调用/system/bin/app_process64 来启动zygote进程,入口app_main.cpp

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

intmain(intargc, charconstargv[])

{

    /* 

zygote传入的参数是:

        -Xzygote

        /system/bin

        --zygote

        --start-system-server

        --socket-name=zygote

    

zygote_secondary传入的参数是:

        -Xzygote

        /system/bin

        --zygote

        --socket-name=zygote_secondary

        --enable-lazy-preload  

    */

    

    ......

 

    // Parse runtime arguments.  Stop at first unrecognized option.

    boolzygote = false;

    boolstartSystemServer = false;

    boolapplication = false;

    String8 niceName;

    String8 className;

 

    ++i;  // Skip unused "parent dir" argument.

    while(i < argc) {

        constchar* arg = argv[i++];

        if(strcmp(arg, "--zygote") == 0) {

            zygote = true;

            //对于64位系统nice_name为zygote64,32位系统为zygote

            niceName = ZYGOTE_NICE_NAME;

        elseif(strcmp(arg, "--start-system-server") == 0) {

            //是否需要启动system server

            startSystemServer = true;

        elseif(strcmp(arg, "--application") == 0) {

            //启动进入独立的程序模式

            application = true;

        elseif(strncmp(arg, "--nice-name=", 12) == 0) {

            //niceName为当前进程别名,区别abi型号

            niceName.setTo(arg + 12);

        elseif(strncmp(arg, "--", 2) != 0) {

            className.setTo(arg);

            break;

        else{

            --i;

            break;

        }

    }

 

    Vector<String8> args;

    if(!className.isEmpty()) {//className不为空,说明是application启动模式

        // We're not in zygote mode, the only argument we need to pass

        // to RuntimeInit is the application argument.

        //

        // The Remainder of args get passed to startup class main(). Make

        // copies of them before we overwrite them with the process name.

        args.add(application ? String8("application") : String8("tool"));

        runtime.setClassNameAndArgs(className, argc - i, argv + i);

 

        if(!LOG_NDEBUG) {

          String8 restOfArgs;

          charconst* argv_new = argv + i;

          intargc_new = argc - i;

          for(intk = 0; k < argc_new; ++k) {

            restOfArgs.append("\"");

            restOfArgs.append(argv_new[k]);

            restOfArgs.append("\" ");

          }

          ALOGV("Class name = %s, args = %s", className.string(), restOfArgs.string());

        }

    else{

        // We're in zygote mode.

        //进入zygote模式

        //新建Dalvik的缓存目录:/data/dalvik-cache

        maybeCreateDalvikCache();

 

        if(startSystemServer) {

            //添加start-system-server参数

            args.add(String8("start-system-server"));

        }

 

        charprop[PROP_VALUE_MAX];

        if(property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) {

            LOG_ALWAYS_FATAL("app_process: Unable to determine ABI list from property %s.",

                ABI_LIST_PROPERTY);

            return11;

        }

 

        String8 abiFlag("--abi-list=");

        abiFlag.append(prop);

        //添加--abi-list=参数

        args.add(abiFlag);

 

        // In zygote mode, pass all remaining arguments to the zygote

        // main() method.

        for(; i < argc; ++i) {

            //将剩下的参数加入args

            args.add(String8(argv[i]));

        }

    }

    

    //设置一个“好听的昵称” zygote\zygote64,之前的名称是app_process

    if(!niceName.isEmpty()) {

        runtime.setArgv0(niceName.string(), true/* setProcName */);

    }

 

    if(zygote) {

        //如果是zygote启动模式,则加载ZygoteInit

        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);

    elseif(className) {

        //如果是application启动模式,则加载RuntimeInit

        runtime.start("com.android.internal.os.RuntimeInit", args, zygote);

    else{

        //没有指定类名或zygote,参数错误

        fprintf(stderr, "Error: no class name or --zygote supplied.\n");

        app_usage();

        LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");

    }

}

Zygote本身是一个Native的应用程序,刚开始的进程名称为“app_process”,运行过程中,通过调用setArgv0将名字改为zygote 或者 zygote64(根据操作系统而来),最后通过runtime的start()方法来真正的加载虚拟机并进入JAVA世界。

在app_main.cpp的最后调用了runtime.start()方法,runtime是AppRuntime的对象,AppRuntime是AndroidRuntime的子类,

进入到AndroidRuntime.cpp#start()

/android/frameworks/base/core/jni/AndroidRuntime.cpp

voidAndroidRuntime::start(constchar* className, constVector<String8>& options, boolzygote)

{

    ALOGD(">>>>>> START %s uid %d <<<<<<\n",

            className != NULL ? className : "(unknown)", getuid());

 

    staticconstString8 startSystemServer("start-system-server");

    // Whether this is the primary zygote, meaning the zygote which will fork system server.

    boolprimary_zygote = false;

 

    ......

        

    /* start the virtual machine */

    JniInvocation jni_invocation;

    jni_invocation.Init(NULL);

    JNIEnv* env;

 

    //启动虚拟机,主要是关于虚拟机参数的设置

    if(startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) {

        return;

    }

    onVmCreated(env);//空函数,没有任何实现

 

    /*

     * Register android functions.

     */

    //注册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;

 

    stringClass = env->FindClass("java/lang/String");

    assert(stringClass != NULL);

    //等价 strArray[0] = "com.android.internal.os.ZygoteInit"

    strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);

    assert(strArray != NULL);

    classNameStr = env->NewStringUTF(className);

    assert(classNameStr != NULL);

    env->SetObjectArrayElement(strArray, 0, classNameStr);

 

    //strArray[1]="start-system-server";

    //strArray[2]="--abi-list=xxx";

    //其中xxx为系统响应的cpu架构类型,比如arm64-v8a

    for(size_ti = 0; i < options.size(); ++i) {

        jstring optionsStr = env->NewStringUTF(options.itemAt(i).string());

        assert(optionsStr != NULL);

        env->SetObjectArrayElement(strArray, i + 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"转换为"com/android/internal/os/ZygoteInit"

    char* slashClassName = toSlashClassName(className != NULL ? className : "");

    jclass startClass = env->FindClass(slashClassName);//找到Zygoteinit

    if(startClass == NULL) {

        ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);

        /* keep going */

    else{

        //找到这个类后,继续找成员函数main方法的Method ID

        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{

            //通过反射调用ZygoteInit.main()方法

            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注册JNI方法
  3. 使用JNI把Zyogte进程启动

在start()方法的最后用来反射调用了ZygoteInit的main函数,Zygote便进入了Java框架层。

进入到ZygoteInit.java#main()

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

publicstaticvoidmain(String[] argv) {

    //1.创建ZygoteServer

   ZygoteServer zygoteServer = null;

 

   // Mark zygote start. This ensures that thread creation will throw

   // an error.

    //调用native函数,确保当前没有其它线程在运行

   ZygoteHooks.startZygoteNoThreadCreation();

 

   // Zygote goes into its own process group.

    //设置pid为0,Zygote进入自己的进程组

   try{

       Os.setpgid(00);

   catch(ErrnoException ex) {

       thrownewRuntimeException("Failed to setpgid(0,0)", ex);

   }

 

   Runnable caller;

   try{

       // Store now for StatsLogging later.

       finallongstartTime = SystemClock.elapsedRealtime();

       finalbooleanisRuntimeRestarted = "1".equals(

               SystemProperties.get("sys.boot_completed"));

 

        //得到systrace的监控TAG

       String bootTimeTag = Process.is64Bit() ? "Zygote64Timing""Zygote32Timing";

       TimingsTraceLog bootTimingsTraceLog = newTimingsTraceLog(bootTimeTag,

               Trace.TRACE_TAG_DALVIK);

       //通过systrace来追踪函数ZygoteInit,可以通过systrace工具来进行分析

       //traceBegin和traceEnd要成对出现,而且需要使用同一个tag

       bootTimingsTraceLog.traceBegin("ZygoteInit");

       //开启DDMS(Dalvik Debug Monitor Service)功能

       //注册所有已知的Java VM的处理块的监听器。线程监听、内存监听、native 堆内存监听、debug模式监听等等

       RuntimeInit.preForkInit();

 

       booleanstartSystemServer = false;

       String zygoteSocketName = "zygote";

       String abiList = null;

       booleanenableLazyPreload = false;

 

       //2.解析app_main.cpp#start()传入的参数

       for(inti = 1; i < argv.length; i++) {

           if("start-system-server".equals(argv[i])) {

               startSystemServer = true;//启动zygote时,才会传入参数:start-system-server

           elseif("--enable-lazy-preload".equals(argv[i])) {

               enableLazyPreload = true;//启动zygote_secondary时,才会传入参数:enable-lazy-preload

           elseif(argv[i].startsWith(ABI_LIST_ARG)) {

               abiList = argv[i].substring(ABI_LIST_ARG.length());//通过属性ro.product.cpu.abilist64\ro.product.cpu.abilist32 从C空间传来的值

           elseif(argv[i].startsWith(SOCKET_NAME_ARG)) {

               zygoteSocketName = argv[i].substring(SOCKET_NAME_ARG.length());//会有两种值:zygote和zygote_secondary

           else{

               thrownewRuntimeException("Unknown command line argument: "+ argv[i]);

           }

       }

 

       //根据传入socket name来决定是创建zygote还是zygote_secondary

       finalbooleanisPrimaryZygote = zygoteSocketName.equals(Zygote.PRIMARY_SOCKET_NAME);

    

       if(!isRuntimeRestarted) {

           if(isPrimaryZygote) {

               FrameworkStatsLog.write(FrameworkStatsLog.BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,

                       BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__ZYGOTE_INIT_START,

                       startTime);

           elseif(zygoteSocketName.equals(Zygote.SECONDARY_SOCKET_NAME)) {

               FrameworkStatsLog.write(FrameworkStatsLog.BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,

                       BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__SECONDARY_ZYGOTE_INIT_START,

                       startTime);

           }

       }

 

       if(abiList == null) {

           thrownewRuntimeException("No ABI list supplied.");

       }

 

       // In some configurations, we avoid preloading resources and classes eagerly.

       // In such cases, we will preload things prior to our first fork.

       // 在第一次zygote启动时,enableLazyPreload为false,执行preload

       if(!enableLazyPreload) {

           //systrace 追踪 ZygotePreload

           bootTimingsTraceLog.traceBegin("ZygotePreload");

           EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,

                   SystemClock.uptimeMillis());

           /// M: Added for BOOTPROF

           addBootEvent("Zygote:Preload Start");

           /// @}

           // 3.加载进程的资源和类

           preload(bootTimingsTraceLog);

           EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,

                   SystemClock.uptimeMillis());

           //systrace结束 ZygotePreload的追踪

           bootTimingsTraceLog.traceEnd(); // ZygotePreload

       }

 

        // Do an initial gc to clean up after startup

        bootTimingsTraceLog.traceBegin("PostZygoteInitGC");

        gcAndFinalize();

        bootTimingsTraceLog.traceEnd(); // PostZygoteInitGC

       

        //结束ZygoteInit的systrace追踪

        bootTimingsTraceLog.traceEnd(); // ZygoteInit

 

        Zygote.initNativeState(isPrimaryZygote);

 

        /// M: Added for BOOTPROF

        addBootEvent("Zygote:Preload End");

        /// @}

        ZygoteHooks.stopZygoteNoThreadCreation();

 

        // 4.调用ZygoteServer 构造函数,创建socket,会根据传入的参数

        // 创建两个socket:/dev/socket/zygote 和 /dev/socket/zygote_secondary

        zygoteServer = newZygoteServer(isPrimaryZygote);

 

        if(startSystemServer) {

            //5.fork出SystemServer

            Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);

 

            // {@code r == null} in the parent (zygote) process, and {@code r != null} in the

            // child (system_server) process.

            //启动SystemServer

            if(r != null) {

                r.run();

                return;

            }

        }

 

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

 

        // The select loop returns early in the child process after a fork and

        // loops forever in the zygote.

        //6.zygote进程进入无限循环,处理请求

        caller = zygoteServer.runSelectLoop(abiList);

    catch(Throwable ex) {

        Log.e(TAG, "System zygote died with fatal exception", ex);

        throwex;

    finally{

        if(zygoteServer != null) {

            zygoteServer.closeServerSocket();

        }

    }

 

    // We're in the child process and have exited the select loop. Proceed to execute the

    // command.

    if(caller != null) {

        caller.run();

    }

}

总结zygoteInit.java#main()完成了:

  1. 创建ZygoteServer
  2. 解析了从app_main.cpp#start()传入的参数
  3. 加载进程的资源和类
  4. 调用ZygoteServer构造函数,创建sokect
  5. fork出SystemServer
  6. zygote进程进入无限循环,处理请求
相关文章
|
2月前
|
Java Android开发 数据安全/隐私保护
Android中多进程通信有几种方式?需要注意哪些问题?
本文介绍了Android中的多进程通信(IPC),探讨了IPC的重要性及其实现方式,如Intent、Binder、AIDL等,并通过一个使用Binder机制的示例详细说明了其实现过程。
273 4
|
3月前
|
API Android开发
Android P 性能优化:创建APP进程白名单,杀死白名单之外的进程
本文介绍了在Android P系统中通过创建应用进程白名单并杀死白名单之外的进程来优化性能的方法,包括设置权限、获取运行中的APP列表、配置白名单以及在应用启动时杀死非白名单进程的代码实现。
60 1
|
3月前
|
Android开发 开发者 Kotlin
Android 多进程情况下判断应用是否处于前台或者后台
本文介绍在多进程环境下判断Android应用前后台状态的方法。通过`ActivityManager`和服务信息`RunningAppProcessInfo`可有效检测应用状态,优化资源使用。提供Kotlin代码示例,帮助开发者轻松集成。
255 8
|
5月前
|
大数据 Linux Android开发
Android ParcelFileDescriptor实现进程间通信
Android ParcelFileDescriptor实现进程间通信
80 0
|
6月前
|
存储 Java Android开发
Zygote进程启动过程
Zygote进程启动过程
46 1
|
6月前
|
XML 前端开发 Android开发
Android架构设计——MVC(1),Android多进程从头讲到尾
Android架构设计——MVC(1),Android多进程从头讲到尾
|
Java Linux Android开发
理解Android进程创建流程
理解Android进程创建流程
106 0
|
6月前
|
安全 Linux API
Android进程与线程
Android进程与线程
49 0
|
Unix Linux Android开发
Android C++系列:Linux进程间通信(二)
mmap可以把磁盘文件的一部分直接映射到内存,这样文件中的位置直接就有对应的内存 地址,对文件的读写可以直接用指针来做而不需要read/write函数。
107 0
|
Android开发
【Android 逆向】Android 进程注入工具开发 ( 远程调用 | x86 架构的返回值获取 | arm 架构远程调用 )
【Android 逆向】Android 进程注入工具开发 ( 远程调用 | x86 架构的返回值获取 | arm 架构远程调用 )
376 0