做室内概念图的网站,黑马程序员培训机构怎么样,1534939978姐的微信德惠市,柳城网站制作一、什么是Zygote
在上一篇文章Android系统启动-init进程详解#xff08;Android 14#xff09;中#xff0c;分析了init进程#xff0c;在init进程启动的第二阶段会解析init.*.rc文件#xff0c;启动多个进程#xff0c;其中包括Zygote。
Zygote又叫孵化器#xff0c…一、什么是Zygote
在上一篇文章Android系统启动-init进程详解Android 14中分析了init进程在init进程启动的第二阶段会解析init.*.rc文件启动多个进程其中包括Zygote。
Zygote又叫孵化器是 Android 系统创建的第一个Java进程它是所有Java进程的父进程。包括 system_server 进程以及所有的App进程都是Zygote的子进程。
Zygote 进程作为 Socket 的 Server 端接收处理系统中创建进程的请求。Android中的应用进程的创建都是应用进程通过 Binder 发送请求给 system_server 进程中的 ActivityManagerService(AMS) AMS 再发送 Socket 消息给 Zygote 进程统一由 Zygote 进程创建出来的。整个过程如下图所示 二、Zygote的启动
app_main.cpp
在init进程启动后会解析 init.rc 文件创建和加载 service 字段指定的 Zygote 进程。在 /system/core/rootdir/init.rc 中通过如下引用来 load zygote 的 rc
import /system/etc/init/hw/init.${ro.zygote}.rc
这里根据属性 ro.zygote 的内容来引入不同的 Zygote 启动脚本。Android 5.0以后Android开始支持64位编译Zygote 进程也随之引入了32/64位的区别。所以这里通过 ro.zygote 属性来控制启动不同版本的 Zygote 进程。 ro.zygote属性会有四种不同的值
zygote32代表32位模式zygote32_64代表32模式为主64位模式为辅zygote64代表64位模式zygote64_32代表64模式为主32位模式为辅
这里我们以64位处理器为例init.zygote64.rc代码如下
// system/core/rootdir/init.zygote64.rcservice zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-namezygoteclass mainpriority -20user rootgroup root readproc reserved_disksocket zygote stream 660 root systemsocket usap_pool_primary stream 660 root systemonrestart exec_background - system system -- /system/bin/vdc volume abort_fuseonrestart write /sys/power/state on# NOTE: If the wakelock name here is changed, then also# update it in SystemSuspend.cpponrestart write /sys/power/wake_lock zygote_kwlonrestart restart audioserveronrestart restart cameraserveronrestart restart mediaonrestart restart media.tuneronrestart restart netdonrestart restart wificondtask_profiles ProcessCapacityHigh MaxPerformancecritical window${zygote.critical_window.minute:-off} targetzygote-fatal
这段脚本要求 init 进程创建一个名为 zygote 的进程该进程要执行的程序是“/system/bin/app_process”。并且为 zygote 进程创建一个 socket 资源 (用于进程间通信ActivityManagerService 就是通过该 socket 请求 zygote 进程 fork 一个应用程序进程)。
app_process64对应的代码定义在 frameworks/base/cmds/app_process 中不管是app_process、app_process32 还是 app_process64 对应的源文件都是 app_main.cpp。
因此Zygote 对应的可执行程序为 app_process该程序对应的源文件为 app_main.cpp入口函数为 main 函数进程名为 Zygote。
// frameworks/base/cmds/app_process/app_main.cpp
int main(int argc, char* const argv[])
{if (!LOG_NDEBUG) {String8 argv_String;for (int i 0; i argc; i) {argv_String.append(\);argv_String.append(argv[i]);argv_String.append(\ );}ALOGV(app_process main with argv: %s, argv_String.string());}//zygote传入的参数argv为“-Xzygote /system/bin --zygote --start-system-server --socket-namezygote”//zygote_secondary传入的参数argv为“-Xzygote /system/bin --zygote --socket-namezygote_secondary”AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));argc--;argv;const char* spaced_commands[] { -cp, -classpath };// Allow spaced commands to be succeeded by exactly 1 argument (regardless of -s).bool known_command false;int i;for (i 0; i argc; i) {if (known_command true) {runtime.addOption(strdup(argv[i]));ALOGV(app_process main add known option %s, argv[i]);known_command false;continue;}for (int j 0;j static_castint(sizeof(spaced_commands) / sizeof(spaced_commands[0]));j) {if (strcmp(argv[i], spaced_commands[j]) 0) {known_command true;ALOGV(app_process main found known command %s, argv[i]);}}if (argv[i][0] ! -) {break;}if (argv[i][1] - argv[i][2] 0) {i; // Skip --.break;}runtime.addOption(strdup(argv[i]));ALOGV(app_process main add option %s, argv[i]);}bool zygote false;bool startSystemServer false;bool application false;String8 niceName;String8 className;i; // Skip unused parent dir argument.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;}}VectorString8 args;if (!className.isEmpty()) {//className不为空说明是application启动模式args.add(application ? String8(application) : String8(tool));runtime.setClassNameAndArgs(className, argc - i, argv i);if (!LOG_NDEBUG) {String8 restOfArgs;char* const* argv_new argv i;int argc_new argc - i;for (int k 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 {//进入zygote模式新建Dalvik的缓存目录:/data/dalvik-cachemaybeCreateDalvikCache();if (startSystemServer) {args.add(String8(start-system-server));}char prop[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);return 11;}String8 abiFlag(--abi-list);abiFlag.append(prop);args.add(abiFlag);// In zygote mode, pass all remaining arguments to the zygote// main() method.for (; i argc; i) {args.add(String8(argv[i]));}}//设置一个“好听的昵称” zygote\zygote64之前的名称是app_processif (!niceName.isEmpty()) {runtime.setArgv0(niceName.string(), true /* setProcName */);}if (zygote) {runtime.start(com.android.internal.os.ZygoteInit, args, zygote);} else if (!className.isEmpty()) {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.);}
}
AndroidRuntime.cpp
在 app_main.cpp 的 main 函数中最后调用了 AndroidRuntime.start 函数
// frameworks/base/core/jni/AndroidRuntime.cpp
void AndroidRuntime::start(const char* className, const VectorString8 options, bool zygote)
{static const String8 startSystemServer(start-system-server);for (size_t i 0; i options.size(); i) {if (options[i] startSystemServer) {const int LOG_BOOT_PROGRESS_START 3000;}}const char* rootDir getenv(ANDROID_ROOT);if (rootDir NULL) {rootDir /system;if (!hasDir(/system)) {return;}setenv(ANDROID_ROOT, rootDir, 1);}JniInvocation jni_invocation;jni_invocation.Init(NULL);JNIEnv* env;// 【虚拟机创建】if (startVm(mJavaVM, env, zygote) ! 0) {return;}onVmCreated(env);// 【JNI方法注册】if (startReg(env) 0) {return;}jclass stringClass;jobjectArray strArray;jstring classNameStr;//等价 strArray new String[options.size() 1];stringClass env-FindClass(java/lang/String);strArray env-NewObjectArray(options.size() 1, stringClass, NULL);//等价 strArray[0] com.android.internal.os.ZygoteInitclassNameStr env-NewStringUTF(className);env-SetObjectArrayElement(strArray, 0, classNameStr);//等价 strArray[1] start-system-server// strArray[2] --abi-listxxx//其中xxx为系统响应的cpu架构类型比如arm64-v8a.for (size_t i 0; i options.size(); i) {jstring optionsStr env-NewStringUTF(options.itemAt(i).string());env-SetObjectArrayElement(strArray, i 1, optionsStr);}//将com.android.internal.os.ZygoteInit转换为com/android/internal/os/ZygoteInitchar* slashClassName toSlashClassName(className);jclass startClass env-FindClass(slashClassName);if (startClass NULL) {...} else {jmethodID startMeth env-GetStaticMethodID(startClass, main,([Ljava/lang/String;)V);// 【通过JNI调用ZygoteInit.main()方法】env-CallStaticVoidMethod(startClass, startMeth, strArray);}//释放相应对象的内存空间free(slashClassName);mJavaVM-DetachCurrentThread();mJavaVM-DestroyJavaVM();
}
start函数主要做了三件事
调用 startVm 创建虚拟机调用 startReg 注册 JNI 方法通过JNI调用到 ZygoteInit.main()进入 Java 框架层此前没有任何代码进入过 Java 框架层
startVM
如果每个应用程序在启动之时都需要单独运行和初始化一个虚拟机会大大降低系统性能因此系统首先在 Zygote 进程中创建一个虚拟机然后通过它孵化出其他的进程这样子进程会获得 Zygote 进程中的 Dalvik 虚拟机实例拷贝进而共享虚拟机内存和框架层资源大幅度提高应用程序的启动和运行速度。
下面只列举部分在调试优化过程中常用参数的源码。
// frameworks/base/core/jni/AndroidRuntime.cpp
int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote)
{// JNI检测功能用于native层调用jni函数时进行常规检测比较弱字符串格式是否符合要求资源是否正确释放。该功能一般用于早期系统调试或手机Eng版对于User版往往不会开启引用该功能比较消耗系统CPU资源降低系统性能。const bool checkJni GetBoolProperty(dalvik.vm.checkjni, false);if (checkJni) {ALOGD(CheckJNI is ON);/* extended JNI checking */addOption(-Xcheck:jni);/* with -Xcheck:jni, this provides a JNI function call trace *///addOption(-verbose:jni);}//虚拟机产生的trace文件主要用于分析系统问题路径默认为/data/anr/traces.txtparseRuntimeOption(dalvik.vm.stack-trace-file, stackTraceFileBuf, -Xstacktracefile:);//对于不同的软硬件环境这些参数往往需要调整、优化从而使系统达到最佳性能parseRuntimeOption(dalvik.vm.heapstartsize, heapstartsizeOptsBuf, -Xms, 4m);parseRuntimeOption(dalvik.vm.heapsize, heapsizeOptsBuf, -Xmx, 16m);parseRuntimeOption(dalvik.vm.heapgrowthlimit, heapgrowthlimitOptsBuf, -XX:HeapGrowthLimit);parseRuntimeOption(dalvik.vm.heapminfree, heapminfreeOptsBuf, -XX:HeapMinFree);parseRuntimeOption(dalvik.vm.heapmaxfree, heapmaxfreeOptsBuf, -XX:HeapMaxFree);parseRuntimeOption(dalvik.vm.heaptargetutilization,heaptargetutilizationOptsBuf, -XX:HeapTargetUtilization);...//初始化虚拟机if (JNI_CreateJavaVM(pJavaVM, pEnv, initArgs) 0) {ALOGE(JNI_CreateJavaVM failed\n);return -1;}
}
startReg
int AndroidRuntime::startReg(JNIEnv* env)
{//设置线程创建方法为javaCreateThreadEtcandroidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc);env-PushLocalFrame(200);//进程 JNI 方法的注册if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) 0) {env-PopLocalFrame(NULL);return -1;}env-PopLocalFrame(NULL);return 0;
}
register_jni_procs
//frameworks/base/core/jni/AndroidRuntime.cppstatic int register_jni_procs(const RegJNIRec array[], size_t count, JNIEnv* env){for (size_t i 0; i count; i) {if (array[i].mProc(env) 0) {//调用gRegJNI的mProc#ifndef NDEBUGALOGD(----------!!! %s failed to load\n, array[i].mName);#endifreturn -1;}}return 0;}//gRegJNI是一个全局数组定义如下:
//frameworks/base/core/jni/AndroidRuntime.cppstatic const RegJNIRec gRegJNI[] {REG_JNI(register_com_android_internal_os_RuntimeInit),REG_JNI(register_com_android_internal_os_ZygoteInit_nativeZygoteInit),REG_JNI(register_android_os_SystemClock),........//frameworks/base/core/jni/AndroidRuntime.cpp#ifdef NDEBUG#define REG_JNI(name) { name }struct RegJNIRec {int (*mProc)(JNIEnv*);};#else#define REG_JNI(name) { name, #name }struct RegJNIRec {int (*mProc)(JNIEnv*);const char* mName;};#endif
gRegJNI数组有100多个成员其中每一项成员都是通过REG_JNI宏定义的。调用 mProc就等价于调用其参数名所指向的函数。 例如 REG_JNI(register_com_android_internal_os_RuntimeInit).mProc 也就是指进入 register_com_android_internal_os_RuntimeInit 方法。
ZygoteInit.java
AndroidRuntime.start() 执行到最后通过反射调用到 ZygoteInit.main()至此第一次进入 Java 世界。
public static void main(String argv[]) {// 1.创建ZygoteServerZygoteServer zygoteServer null; // 调用native函数确保当前没有其它线程在运行ZygoteHooks.startZygoteNoThreadCreation(); //设置pid为0Zygote进入自己的进程组Os.setpgid(0, 0);........Runnable caller;try {........//得到systrace的监控TAGString bootTimeTag Process.is64Bit() ? Zygote64Timing : Zygote32Timing;TimingsTraceLog bootTimingsTraceLog new TimingsTraceLog(bootTimeTag,Trace.TRACE_TAG_DALVIK);//通过systradce来追踪 函数ZygoteInit 可以通过systrace工具来进行分析//traceBegin 和 traceEnd 要成对出现而且需要使用同一个tagbootTimingsTraceLog.traceBegin(ZygoteInit); //开启DDMS(Dalvik Debug Monitor Service)功能//注册所有已知的Java VM的处理块的监听器。//线程监听、内存监听、native 堆内存监听、debug模式监听等等RuntimeInit.preForkInit(); boolean startSystemServer false;String zygoteSocketName zygote;String abiList null;boolean enableLazyPreload false; //2. 解析app_main.cpp - start()传入的参数for (int i 1; i argv.length; i) {if (start-system-server.equals(argv[i])) {startSystemServer true;//启动zygote时才会传入参数start-system-server} else if (--enable-lazy-preload.equals(argv[i])) {enableLazyPreload true;//启动zygote_secondary时才会传入参数enable-lazy-preload} else if (argv[i].startsWith(ABI_LIST_ARG)) { //通过属性ro.product.cpu.abilist64\ro.product.cpu.abilist32 从C空间传来的值abiList argv[i].substring(ABI_LIST_ARG.length());} else if (argv[i].startsWith(SOCKET_NAME_ARG)) {zygoteSocketName argv[i].substring(SOCKET_NAME_ARG.length());//会有两种值zygote和zygote_secondary} else {throw new RuntimeException(Unknown command line argument: argv[i]);}} // 根据传入socket name来决定是创建zygote还是zygote_secondaryfinal boolean isPrimaryZygote zygoteSocketName.equals(Zygote.PRIMARY_SOCKET_NAME);// 在第一次zygote启动时enableLazyPreload为false执行preloadif (!enableLazyPreload) {//systrace 追踪 ZygotePreloadbootTimingsTraceLog.traceBegin(ZygotePreload);// 3.加载进程的资源和类preload(bootTimingsTraceLog);//systrae结束 ZygotePreload的追踪bootTimingsTraceLog.traceEnd(); // ZygotePreload}//结束ZygoteInit的systrace追踪bootTimingsTraceLog.traceEnd(); // ZygoteInit//禁用systrace追踪以便fork的进程不会从zygote继承过时的跟踪标记Trace.setTracingEnabled(false, 0); // 4.调用ZygoteServer 构造函数创建socket会根据传入的参数// 创建两个socket/dev/socket/zygote 和 /dev/socket/zygote_secondaryzygoteServer new ZygoteServer(isPrimaryZygote);if (startSystemServer) {//5.fork出system serverRunnable r forkSystemServer(abiList, zygoteSocketName, zygoteServer); // 启动SystemServerif (r ! null) {r.run();return;}} // 6.zygote进程进入无限循环处理请求caller zygoteServer.runSelectLoop(abiList);} catch (Throwable ex) {Log.e(TAG, System zygote died with exception, ex);throw ex;} finally {if (zygoteServer ! null) {zygoteServer.closeServerSocket();}} // 7.在子进程中退出了选择循环。继续执行命令if (caller ! null) {caller.run();}}ZygoteInit 的 main 函数主要完成了以下工作
调用 preload() 来预加载类和资源调用 ZygoteServer() 创建了两个 Server 端的 Socket 分别为 /dev/socket/zygote 和 /dev/socket/zygote_secondarySocket 用来等待 AMS 发送过来的请求请求 zygote 进程创建新的应用程序进程。调用 forkSystemServer 来启动 SystemServer 进程这样系统的关键服务也会通过 SystemServer 进程启动起来。最后调用 runSelectLoop 函数来等待客户端请求
总结
1.首先解析 init.rc 文件创建 Zygote 进程执行 app_process 程序该程序入口为 app_main.cpp 的 main 函数。
2.在 app_main.cpp 中调用 AndroidRuntime.start 函数在 start() 函数中调用 startVm() 创建 Java 虚拟机然后调用 startReg() 来注册 JNI 函数最后通过 JNI 调用到 ZygoteInit.main()进入 Java 框架层此前没有任何代码进入过 Java 框架层。
3.在 ZygoteInit.main() 中调用 preload() 预加载类和资源调用 ZygoteServer() 构造函数创建了两个Socket用于响应 AMS 发送的请求。调用 forkSystemServer() 启动 SystemServer 进程。最后调用 runSelectLoop() 循环等待 AMS 的请求。