当前位置: 首页 > article >正文

Android 12系统源码_系统启动(二)Zygote进程

前言

Zygote(意为“受精卵”)是 Android 系统中的一个核心进程,负责 孵化(fork)应用进程,以优化应用启动速度和内存占用。它是 Android 系统启动后第一个由 init 进程启动的 Java 进程,后续所有 Android 应用进程(如 system_server 和用户应用)都由它 fork 而来。Zygote主要有以下几种作用。

  • 预加载 Java 类和资源
    在启动时加载 Android 核心类(如 Activity、View、Context)和系统资源(如 framework-res.apk),避免每个应用重复加载,节省内存和时间。

  • 进程孵化(fork)
    当启动新应用时,Zygote 会 fork 自身,生成一个新的子进程(即应用进程),并继承已预加载的类,减少启动开销。

  • 安全管理
    继承 Zygote 的安全策略(如 SELinux 上下文、UID/GID),确保应用运行在正确的权限环境下。

搜寻Zygote源码位置

我们在Android 12系统源码_系统启动(一)init进程这篇文章中有提到过init.rc脚本。

system/core/rootdir/init.rc

import /init.environ.rc
import /system/etc/init/hw/init.usb.rc
import /init.${ro.hardware}.rc
import /vendor/etc/init/hw/init.${ro.hardware}.rc
import /system/etc/init/hw/init.usb.configfs.rc
import /system/etc/init/hw/init.${ro.zygote}.rc

实际运行中的系统中,/system/etc/init/hw目录的具体内容如下所示:

# 进入/system/etc/init/hw目录,输入ls指令
# 可以看到如下内容init.rc  init.usb.configfs.rc  init.usb.rc  init.zygote32.rc  init.zygote64_32.rc

由于我本地的系统getprop ro.zygote的值是zygote64_32,这样init.rc引用的自然就是init.zygote64_32.rc脚本文件,Android系统/system/etc/init/hw/目录中的.rc脚本,最初都是从源码system/core/rootdir目录拷贝而来的。
rootdir目录

service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygoteclass 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 ononrestart restart audioserveronrestart restart cameraserveronrestart restart mediaonrestart restart netdonrestart restart wificondtask_profiles ProcessCapacityHigh MaxPerformancecritical window=${zygote.critical_window.minute:-off} target=zygote-fatal

结合以上代码可以知道init启动了zygote服务,对应的就是/system/bin/app_process64这个程序。
在aosp源码中通过以下指令进行搜索

grep "app_process" -rn ./ --include="*.bp"

通过以上指令我们可以定位到如下内容
搜索结果
可以知道app_process程序对应的源码地址为frameworks/base/cmds/app_process

Zygote入口函数

frameworks/base/cmds/app_process/app_main.cpp

class AppRuntime : public AndroidRuntime
{
public:AppRuntime(char* argBlockStart, const size_t argBlockLength): AndroidRuntime(argBlockStart, argBlockLength), mClass(NULL){}
}
#if defined(__LP64__)
static const char ABI_LIST_PROPERTY[] = "ro.product.cpu.abilist64";
static const char ZYGOTE_NICE_NAME[] = "zygote64";
#else
static const char ABI_LIST_PROPERTY[] = "ro.product.cpu.abilist32";
static const char ZYGOTE_NICE_NAME[] = "zygote";
#endif
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());}//注释1,进行AppRuntime的构造AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));// 忽略 argv[0](程序名)argc--;argv++;const char* spaced_commands[] = { "-cp", "-classpath" };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_cast<int>(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;//跳过 "parent dir" 参数  //解析启动模式while (i < argc) {const char* arg = argv[i++];if (strcmp(arg, "--zygote") == 0) {zygote = true;niceName = ZYGOTE_NICE_NAME;// "zygote" 或 "zygote64"} else if (strcmp(arg, "--start-system-server") == 0) {startSystemServer = true; // 启动 system_server} else if (strcmp(arg, "--application") == 0) {application = true;// 标记为普通应用} else if (strncmp(arg, "--nice-name=", 12) == 0) {niceName.setTo(arg + 12);// 设置进程名(如 "webview_zygote")} else if (strncmp(arg, "--", 2) != 0) {className.setTo(arg);break;} else {--i;break;}}//准备启动参数Vector<String8> args;if (!className.isEmpty()) {// 普通 Java 模式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 模式maybeCreateDalvikCache();// 确保 Dalvik 缓存目录存在if (startSystemServer) {args.add(String8("start-system-server"));// 告知 Zygote 启动 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);// 添加剩余参数for (; i < argc; ++i) {args.add(String8(argv[i]));}}if (!niceName.isEmpty()) {// 设置进程名(如 "zygote")runtime.setArgv0(niceName.string(), true /* setProcName */);}if (zygote) {//注释2,启动 JVM,调用ZygoteInit.main(),进入 Zygote 的主循环。runtime.start("com.android.internal.os.ZygoteInit", args, zygote);} else if (className) {//启动 JVM,调用 RuntimeInit.main(),直接运行指定的 Java 类。runtime.start("com.android.internal.os.RuntimeInit", args, zygote);} else {fprintf(stderr, "Error: no class name or --zygote supplied.\n");app_usage();LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");}
}

在注释1处,进行AppRuntime的构造,该类继承自AndroidRuntime。
由于我们这里主要是分析zgote主线逻辑,继续关注注释2处,调用runtime的start方法。

AndroidRuntime的start方法

frameworks/base/core/jni/AndroidRuntime.cpp

void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{//日志打印 AndroidRuntime: >>>>>> START com.android.internal.os.ZygoteInitALOGD(">>>>>> START %s uid %d <<<<<<\n",className != NULL ? className : "(unknown)", getuid());static const String8 startSystemServer("start-system-server");// Whether this is the primary zygote, meaning the zygote which will fork system server.bool primary_zygote = false;...代码省略...JniInvocation jni_invocation;jni_invocation.Init(NULL);JNIEnv* env;//启动java需要的jvm环境,才可以运行java代码if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) {return;}onVmCreated(env);/** Register android functions.*/if (startReg(env) < 0) {ALOGE("Unable to register all android natives\n");return;}jclass stringClass;jobjectArray strArray;jstring classNameStr;stringClass = env->FindClass("java/lang/String");assert(stringClass != NULL);strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);assert(strArray != NULL);classNameStr = env->NewStringUTF(className);assert(classNameStr != NULL);env->SetObjectArrayElement(strArray, 0, classNameStr);for (size_t i = 0; i < options.size(); ++i) {jstring optionsStr = env->NewStringUTF(options.itemAt(i).string());assert(optionsStr != NULL);env->SetObjectArrayElement(strArray, i + 1, optionsStr);}char* slashClassName = toSlashClassName(className != NULL ? className : "");jclass startClass = env->FindClass(slashClassName);if (startClass == NULL) {ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);} else {jmethodID startMeth = env->GetStaticMethodID(startClass, "main","([Ljava/lang/String;)V");if (startMeth == NULL) {ALOGE("JavaVM unable to find main() in '%s'\n", className);} else {//调用ZygoteInit类的main方法//startClass = com.android.internal.os.ZygoteInit//startMeth = main//strArray 字符串集合,存放方法参数env->CallStaticVoidMethod(startClass, startMeth, strArray);}}...代码省略...
}

app_main主要做的工作就是准备虚拟机环境,让进程运行到了java世界的ZygoteInit的main方法

ZygoteInit的main方法

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

public class ZygoteInit {public static void main(String[] argv) {ZygoteServer zygoteServer = null;//禁止在 Zygote 中创建线程,确保调用fork()方法构建子进程时进程状态简单。ZygoteHooks.startZygoteNoThreadCreation();try {//将 Zygote 设为独立的进程组,避免被信号误杀。Os.setpgid(0, 0);} catch (ErrnoException ex) {throw new RuntimeException("Failed to setpgid(0,0)", ex);}Runnable caller;try {// 记录启动时间(用于性能统计)final long startTime = SystemClock.elapsedRealtime();final boolean isRuntimeRestarted = "1".equals(SystemProperties.get("sys.boot_completed"));// 初始化 Trace 和日志工具(区分 32/64 位 Zygote)String bootTimeTag = Process.is64Bit() ? "Zygote64Timing" : "Zygote32Timing";// 用于记录启动耗时TimingsTraceLog bootTimingsTraceLog = new TimingsTraceLog(bootTimeTag,Trace.TRACE_TAG_DALVIK);bootTimingsTraceLog.traceBegin("ZygoteInit");RuntimeInit.preForkInit();// 初始化运行时环境boolean startSystemServer = false;String zygoteSocketName = "zygote";String abiList = null;boolean enableLazyPreload = false;for (int i = 1; i < argv.length; i++) {if ("start-system-server".equals(argv[i])) {//是否启动 system_serverstartSystemServer = true;} else if ("--enable-lazy-preload".equals(argv[i])) {//是否延迟预加载(优化启动速度)enableLazyPreload = true;} else if (argv[i].startsWith(ABI_LIST_ARG)) {// 支持的 CPU ABI 列表abiList = argv[i].substring(ABI_LIST_ARG.length());} else if (argv[i].startsWith(SOCKET_NAME_ARG)) {// "--socket-name="zygoteSocketName = argv[i].substring(SOCKET_NAME_ARG.length());} else {throw new RuntimeException("Unknown command line argument: " + argv[i]);}}final boolean isPrimaryZygote = 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);} else if (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) {throw new RuntimeException("No ABI list supplied.");}if (!enableLazyPreload) {bootTimingsTraceLog.traceBegin("ZygotePreload");EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,SystemClock.uptimeMillis());preload(bootTimingsTraceLog);// 注释1,预加载类、资源、OpenGL等EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,SystemClock.uptimeMillis());bootTimingsTraceLog.traceEnd();// ZygotePreload}// Do an initial gc to clean up after startupbootTimingsTraceLog.traceBegin("PostZygoteInitGC");gcAndFinalize();// 触发 GC 清理预加载后的内存bootTimingsTraceLog.traceEnd();// PostZygoteInitGCbootTimingsTraceLog.traceEnd();// ZygoteInitZygote.initNativeState(isPrimaryZygote);// 初始化 Native 层状态ZygoteHooks.stopZygoteNoThreadCreation();//解除线程创建限制,允许后续操作创建线程。zygoteServer = new ZygoteServer(isPrimaryZygote);//构造方法中会创建Zygote端需要的socketif (startSystemServer) {// 注释1,fork出system_server子进程Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);//如果是父进程则返回null,如果是system_server子进程则返回SystemServerRunnableif (r != null) {r.run();return;}}Log.i(TAG, "Accepting command socket connections");//注释3,阻塞监听Socket,这轮询会在zygote进程中无限循环,但是如果fork出子进程(system_server或者Android应用进程)就会退出来caller = zygoteServer.runSelectLoop(abiList);} catch (Throwable ex) {Log.e(TAG, "System zygote died with fatal exception", ex);throw ex;} finally {if (zygoteServer != null) {//system_server进程和android应用进程会关闭socket,zygote仍然在runSelectLoop中轮询监听socketzygoteServer.closeServerSocket();}}if (caller != null) {caller.run(); // 注释4,在子进程中执行(如启动 ActivityThread)}}
}

在注释1处调用preload方法进行预加载。
在注释2处调用 Zygote.forkSystemServer() 创建system_server子进程,如果是父进程则返回null,如果是子进程则返回SystemServer的Runnable对象,并进一步调用该Runnable对象的run方法,最终会进入SystemServer的main方法中,加载Android系统需要的各种服务。
在注释3处调用zygoteServer的runSelectLoop方法阻塞监听Socket,等待 AMS 发送 fork 请求,收到请求后创建对应的子进程。
以上就是ZygoteInit的main方法的主要代码,下面我们具体分析一下。
在注释4处,如果当前是子进程,其实就是应用进程,则调用其返回的Runnable的run方法,最终会进入ActivityThread的main方法。

预加载

注释1处调用preload方法,预加载以下内容。

    static void preload(TimingsTraceLog bootTimingsTraceLog) {Log.d(TAG, "begin preload");...代码省略...beginPreload();...代码省略...preloadClasses();//加载/system/etc/preloaded-classes目录下的类。...代码省略...preloadResources();//加载系统资源/system/framework/framework-res.apk...代码省略...preloadSharedLibraries();preloadTextResources();...代码省略...Log.d(TAG, "end preload");sPreloadComplete = true;}

孵化子进程,返回Runnable对象

在注释2处调用 Zygote.forkSystemServer() 孵化system_server子进程,如果是父进程则返回null,如果是子进程则返回实现了Runnable接口的MethodAndArgsCaller对象,并进一步调用该Runnable对象的run方法,最终会进入SystemServer的main方法中,加载Android系统需要的各种服务。

孵化system_server子进程

public class ZygoteInit {private static Runnable forkSystemServer(String abiList, String socketName,ZygoteServer zygoteServer) {...代码省略.../* Hardcoded command line to start the system server */String[] args = {"--setuid=1000",//用户id"--setgid=1000",//组id"--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,"+ "1024,1032,1065,3001,3002,3003,3006,3007,3009,3010,3011,3012","--capabilities=" + capabilities + "," + capabilities,"--nice-name=system_server","--runtime-args","--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,"com.android.server.SystemServer",//SystemServer类名,只有这个条目是非--开头的};ZygoteArguments parsedArgs;int pid;try {...代码省略...parsedArgs = ZygoteArguments.getInstance(commandBuffer);...代码省略.../*调用Zygote的forkSystenServer方法fork system_server进程*/pid = Zygote.forkSystemServer(parsedArgs.mUid, parsedArgs.mGid,parsedArgs.mGids,parsedArgs.mRuntimeFlags,null,parsedArgs.mPermittedCapabilities,parsedArgs.mEffectiveCapabilities);} catch (IllegalArgumentException ex) {throw new RuntimeException(ex);}if (pid == 0) {...代码省略...//由于zygoteServer只有Zygote会使用,子进程system_server不需要使用,于是会将其关闭。zygoteServer.closeServerSocket();//继续调用handleSystemServerProcess方法return handleSystemServerProcess(parsedArgs);}return null;}
}   
>frameworks/base/core/java/com/android/internal/os/Zygote.javapublic final class Zygote {static int forkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {...代码省略...int pid = nativeForkSystemServer(uid, gid, gids, runtimeFlags, rlimits,permittedCapabilities, effectiveCapabilities);...代码省略...return pid;}   private static native int nativeForkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,int[][] rlimits, long permittedCapabilities, long effectiveCapabilities);     }

开启线程池,返回实现了Runnable接口的MethodAndArgsCaller对象

public class ZygoteInit {private static Runnable handleSystemServerProcess(ZygoteArguments parsedArgs) {...代码省略...//从环境变量SYSTEMSERVERCLASSPATH获取到SystemServer类文件相应jar包的路径final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");if (systemServerClasspath != null) {//对相应的jar包做dex优化处理performSystemServerDexOpt(systemServerClasspath);...代码省略...}...代码省略...ClassLoader cl = getOrCreateSystemServerClassLoader();//创建类加载器if (cl != null) {Thread.currentThread().setContextClassLoader(cl);}//调用ZygoteInit的zygoteInit方法return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,parsedArgs.mDisabledCompatChanges,parsedArgs.mRemainingArgs, cl);}public static Runnable zygoteInit(int targetSdkVersion, long[] disabledCompatChanges,String[] argv, ClassLoader classLoader) {...代码省略...RuntimeInit.redirectLogStreams();RuntimeInit.commonInit();//调用native方法,主要是开启ProcessState线程池,用来进行binder通信ZygoteInit.nativeZygoteInit();//调用RuntimeInit的applicationInit方法return RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv,classLoader);}private static native void nativeZygoteInit();  }>frameworks/base/core/jni/AndroidRuntime.cppint register_com_android_internal_os_ZygoteInit_nativeZygoteInit(JNIEnv* env)
{const JNINativeMethod methods[] = {{ "nativeZygoteInit", "()V",(void*) com_android_internal_os_ZygoteInit_nativeZygoteInit },};return jniRegisterNativeMethods(env, "com/android/internal/os/ZygoteInit",methods, NELEM(methods));
}
static void com_android_internal_os_ZygoteInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{gCurRuntime->onZygoteInit();
}>frameworks/base/cmds/app_process/app_main.cppvirtual void onZygoteInit(){sp<ProcessState> proc = ProcessState::self();ALOGV("App process: starting thread pool.\n");proc->startThreadPool();//开启线程池}>frameworks/base/core/java/com/android/internal/os/RuntimeInit.javapublic class RuntimeInit {protected static Runnable applicationInit(int targetSdkVersion, long[] disabledCompatChanges,String[] argv, ClassLoader classLoader) {...代码省略...final Arguments args = new Arguments(argv);//解析参数argvreturn findStaticMain(args.startClass, args.startArgs, classLoader);}static class Arguments {String startClass;//类路径String[] startArgs;//参数Arguments(String args[]) throws IllegalArgumentException {parseArgs(args);}private void parseArgs(String args[])throws IllegalArgumentException {int curArg = 0;for (; curArg < args.length; curArg++) {String arg = args[curArg];if (arg.equals("--")) {curArg++;break;} else if (!arg.startsWith("--")) {//com.android.server.SystemServer字符串break;}}if (curArg == args.length) {throw new IllegalArgumentException("Missing classname argument to RuntimeInit!");}startClass = args[curArg++];startArgs = new String[args.length - curArg];System.arraycopy(args, curArg, startArgs, 0, startArgs.length);}        }    protected static Runnable findStaticMain(String className, String[] argv, ClassLoader classLoader) {Class<?> cl;...代码省略..//获取到SystemServer的类字节cl = Class.forName(className, true, classLoader);...代码省略..Method m;//获取到main方法的方法idm = cl.getMethod("main", new Class[] { String[].class });...代码省略..//这个就是ZygoteInit类中forkSystemServer的返回值rreturn new MethodAndArgsCaller(m, argv);}static class MethodAndArgsCaller implements Runnable {private final Method mMethod;private final String[] mArgs;public MethodAndArgsCaller(Method method, String[] args) {mMethod = method;mArgs = args;}public void run() {...代码省略...//通过反射调用mMethod静态方法,这里触发的其实就是SystemServer的main方法mMethod.invoke(null, new Object[] { mArgs });...代码省略...}}}

监听socket,等待AMS发送fork请求

注释3处调用zygoteServer的runSelectLoop方法阻塞监听Socket,等待 AMS 发送 fork 请求,收到请求后创建对应的子进程。

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

class ZygoteServer {private LocalServerSocket mZygoteSocket;//服务端socketZygoteServer(boolean isPrimaryZygote) {...代码省略...//调用Zygote的createManagedSocketFromInitSocket方法创建Zygote端需要的socketmZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.PRIMARY_SOCKET_NAME);...代码省略...       }/*** 开启zygote进程轮询监听。接收新的socket连接(会创建新的ZygoteConnection)* 并且从这些链接中中读取命令,并且执行*/Runnable runSelectLoop(String abiList) {ArrayList<FileDescriptor> socketFDs = new ArrayList<>();ArrayList<ZygoteConnection> peers = new ArrayList<>();socketFDs.add(mZygoteSocket.getFileDescriptor());peers.add(null);...代码省略...int pollReturnValue;try {//开启轮询pollReturnValue = Os.poll(pollFDs, pollTimeoutMs);} catch (ErrnoException ex) {throw new RuntimeException("poll failed", ex);}if (pollReturnValue == 0) {mUsapPoolRefillTriggerTimestamp = INVALID_TIMESTAMP;mUsapPoolRefillAction = UsapPoolRefillAction.DELAYED;} else {boolean usapPoolFDRead = false;while (--pollIndex >= 0) {if ((pollFDs[pollIndex].revents & POLLIN) == 0) {continue;}if (pollIndex == 0) {//如果是新的socket链接请求(建立新连接)//新建ZygoteConnection链接ZygoteConnection newPeer = acceptCommandPeer(abiList);//添加到链接数组中peers.add(newPeer);//添加到文件描述符数组中socketFDs.add(newPeer.getFileDescriptor());} else if (pollIndex < usapPoolEventFDIndex) {//如果是之前已经建立的socket链接(在已有连接上)try {//获取对应的ZygoteConnectionZygoteConnection connection = peers.get(pollIndex);boolean multipleForksOK = !isUsapPoolEnabled()&& ZygoteHooks.isIndefiniteThreadSuspensionSafe();//会执行ZygoteConnection发送过来的命令final Runnable command = connection.processCommand(this, multipleForksOK);if (mIsForkChild) {//子进程...代码省略...//退出,command就是前面的ZygoteInit的caller对象return command;} else {//父进程,上面是while无限循环,zygote进程永远不会退出...代码省略...if (connection.isClosedByPeer()) {connection.closeSocket();peers.remove(pollIndex);socketFDs.remove(pollIndex);}}} catch (Exception e) {...代码省略...} finally {mIsForkChild = false;}}}}}
}
>frameworks/base/core/java/com/android/internal/os/Zygote.java
public final class Zygote {public static final String PRIMARY_SOCKET_NAME = "zygote";private static final String ANDROID_SOCKET_PREFIX = "ANDROID_SOCKET_";static LocalServerSocket createManagedSocketFromInitSocket(String socketName) {int fileDesc;//fullSocketName为“ANDROID_SOCKET_zygote”final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;try {//获取ANDROID_SOCKET_zygote的坏境变量(即为/dev/socket/zygote的文件描述符的值)//该变量是init进程在启动zygote进程时保存到环境变量中的String env = System.getenv(fullSocketName);fileDesc = Integer.parseInt(env);} catch (RuntimeException ex) {throw new RuntimeException("Socket unset or invalid: " + fullSocketName, ex);}try {//绑定socket,在后面用来接收Android应用启动请求FileDescriptor fd = new FileDescriptor();fd.setInt$(fileDesc);return new LocalServerSocket(fd);} catch (IOException ex) {throw new RuntimeException("Error building socket from file descriptor: " + fileDesc, ex);}}
}

fork应用进程,进入ActivityThread的Main方法

ZygoteConnection的processCommand方法如下所示。

class ZygoteConnection {Runnable processCommand(ZygoteServer zygoteServer, boolean multipleOK) {...代码省略...//fork子进程pid = Zygote.forkAndSpecialize(parsedArgs.mUid, parsedArgs.mGid,parsedArgs.mGids, parsedArgs.mRuntimeFlags, rlimits,parsedArgs.mMountExternal, parsedArgs.mSeInfo, parsedArgs.mNiceName,fdsToClose, fdsToIgnore, parsedArgs.mStartChildZygote,parsedArgs.mInstructionSet, parsedArgs.mAppDataDir,parsedArgs.mIsTopApp, parsedArgs.mPkgDataInfoList,parsedArgs.mAllowlistedDataInfoList, parsedArgs.mBindMountAppDataDirs,parsedArgs.mBindMountAppStorageDirs);try {if (pid == 0) {//当前进程是子进程中(应用进程中)zygoteServer.setForkChild();zygoteServer.closeServerSocket();IoUtils.closeQuietly(serverPipeFd);serverPipeFd = null;//继续调用handleChildProc方法return handleChildProc(parsedArgs, childPipeFd,parsedArgs.mStartChildZygote);} else {//当前进程是父进程中(zygote)return null;}} ...代码省略...}private Runnable handleChildProc(ZygoteArguments parsedArgs,FileDescriptor pipeFd, boolean isZygote) {//关闭ZygoteConnection中的socket链接closeSocket();Zygote.setAppProcessName(parsedArgs, TAG);...代码省略...if (!isZygote) {//执行ZygoteInit的zygoteInit方法,这里返回的是ActivityThread的main方法的Runnablereturn ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,parsedArgs.mDisabledCompatChanges,parsedArgs.mRemainingArgs, null /* classLoader */);} else {return ZygoteInit.childZygoteInit(parsedArgs.mRemainingArgs  /* classLoader */);}}
}

如果当前进程是应用子进程,则会返回的是ActivityThread的main方法,最终会进入ActivityThread的main方法中。

时序图

从Zygote进程所在的Native层 -> ZygoteInit所在的JVM层 -> SystemServer进程的启动
时序图

相关文章:

Android 12系统源码_系统启动(二)Zygote进程

前言 Zygote&#xff08;意为“受精卵”&#xff09;是 Android 系统中的一个核心进程&#xff0c;负责 孵化&#xff08;fork&#xff09;应用进程&#xff0c;以优化应用启动速度和内存占用。它是 Android 系统启动后第一个由 init 进程启动的 Java 进程&#xff0c;后续所有…...

MOSN(Modular Open Smart Network)-05-MOSN 平滑升级原理解析

前言 大家好&#xff0c;我是老马。 sofastack 其实出来很久了&#xff0c;第一次应该是在 2022 年左右开始关注&#xff0c;但是一直没有深入研究。 最近想学习一下 SOFA 对于生态的设计和思考。 sofaboot 系列 SOFAStack-00-sofa 技术栈概览 MOSN&#xff08;Modular O…...

Flink介绍与安装

Apache Flink是一个在有界数据流和无界数据流上进行有状态计算分布式处理引擎和框架。Flink 设计旨在所有常见的集群环境中运行&#xff0c;以任意规模和内存级速度执行计算。 一、主要特点和功能 1. 实时流处理: 低延迟: Flink 能够以亚秒级的延迟处理数据流&#xff0c;非常…...

【gradio】从零搭建知识库问答系统-Gradio+Ollama+Qwen2.5实现全流程

从零搭建大模型问答系统-GradioOllamaQwen2.5实现全流程&#xff08;一&#xff09; 前言一、界面设计&#xff08;计划&#xff09;二、模块设计1.登录模块2.注册模块3. 主界面模块4. 历史记录模块 三、相应的接口&#xff08;前后端交互&#xff09;四、实现前端界面的设计co…...

PowerBI,用度量值实现表格销售统计(含合计)的简单示例

假设我们有产品表 和销售表 我们想实现下面的效果 表格显示每个产品的信息&#xff0c;以及单个产品的总销量 有一个切片器能筛选各个门店的产品销量 还有一个卡片图显示所筛选条件下&#xff0c;所有产品的总销量 实现方法&#xff1a; 1.我们新建一个计算表&#xff0c;把…...

Mac 常用命令

一、文件操作(必知必会)​ ​1. 快速导航 cd ~/Documents # 进入文档目录 cd .. # 返回上级目录 pwd # 显示当前路径 2. ​文件管理 touch new_file.txt # 创建空文件 mkdir -p project/{src,docs} # 递归创建目录 cp …...

26考研——查找_树形查找_二叉排序树(BST)(7)

408答疑 文章目录 三、树形查找二叉排序树&#xff08;BST&#xff09;二叉排序树中结点值之间的关系二叉树形查找二叉排序树的查找过程示例 向二叉排序树中插入结点插入过程示例 构造二叉排序树的过程构造示例 二叉排序树中删除结点的操作情况一&#xff1a;被删除结点是叶结点…...

美摄科技开启智能汽车车内互动及娱乐解决方案2.0

在科技飞速发展的今天&#xff0c;汽车已不再仅仅是简单的代步工具&#xff0c;而是逐渐演变为集出行、娱乐、社交于一体的智能移动空间。美摄科技&#xff0c;作为前沿视觉技术与人工智能应用的领航者&#xff0c;凭借其卓越的技术实力和创新精神&#xff0c;携手汽车行业&…...

【行驶证识别】批量咕嘎OCR识别行驶证照片复印件图片里的文字信息保存表格或改名字,基于QT和腾讯云api_ocr的实现方式

项目背景 在许多业务场景中,如物流管理、车辆租赁、保险理赔等,常常需要处理大量的行驶证照片复印件。手动录入行驶证上的文字信息,像车主姓名、车辆型号、车牌号码等,不仅效率低下,还容易出现人为错误。借助 OCR(光学字符识别)技术,能够自动识别行驶证图片中的文字信…...

Vue-admin-template安装教程

#今天配置后台管理模板发现官方文档的镜像网站好像早失效了&#xff0c;自己稍稍总结了一下方法# 该项目环境需要node17及以下&#xff0c;如果npm install这一步报错可能是这个原因 git clone https://github.com/PanJiaChen/vue-admin-template.git cd vue-admin-template n…...

21.Excel自动化:如何使用 xlwings 进行编程

一 将Excel用作数据查看器 使用 xlwings 中的 view 函数。 1.导包 import datetime as dt import xlwings as xw import pandas as pd import numpy as np 2.view 函数 创建一个基于伪随机数的DataFrame&#xff0c;它有足够多的行&#xff0c;使得只有首尾几行会被显示。 df …...

LabVIEW FPGA与Windows平台数据滤波处理对比

LabVIEW在FPGA和Windows平台均可实现数据滤波处理&#xff0c;但两者的底层架构、资源限制、实时性及应用场景差异显著。FPGA侧重硬件级并行处理&#xff0c;适用于高实时性场景&#xff1b;Windows依赖软件算法&#xff0c;适合复杂数据处理与可视化。本文结合具体案例&#x…...

【NLP 48、大语言模型的神秘力量 —— ICL:in context learning】

目录 一、ICL的优势 1.传统做法 2.ICL做法 二、ICL的发展 三、ICL成因的两种看法 1.meta learning 2.Bayesian Inference 四、ICL要点 ① 语言模型的规模 ② 提示词prompt中提供的examples数量和顺序 ③ 提示词prompt的形式&#xff08;format&#xff09; 五、fine-tune VS I…...

vue 中渲染 markdown 格式的文本

文章目录 需求分析第一步:安装依赖第二步:创建 Markdown 渲染组件第三步,使用实例扩展功能1. 代码高亮:2. 自定义渲染规则:需求 渲染 markdown 格式的文本 分析 在Vue 3中实现Markdown渲染的常见方法。通常有两种方式:使用现有的Markdown解析库,或者自己编写解析器…...

工业4G路由器赋能智慧停车场高效管理

工业4G路由器作为智慧停车场管理系统通信核心&#xff0c;将停车场内的各个子系统连接起来&#xff0c;包括车牌识别系统、道闸控制系统、车位检测系统、收费系统以及监控系统等。通过4G网络&#xff0c;将这些系统采集到的数据传输到云端服务器或管理中心&#xff0c;实现信息…...

卡尔曼滤波入门(二)

核心思想 卡尔曼滤波的核心就是在不确定中寻找最优&#xff0c;那么怎么定义最优呢&#xff1f;答案是均方误差最小的&#xff0c;便是最优。 卡尔曼滤波本质上是一种动态系统状态估计器&#xff0c;它回答了这样一个问题&#xff1a; 如何从充满噪声的观测数据中&#xff0c…...

企业如何平稳实现从Tableau到FineBI的信创迁移?

之前和大家分享了《如何将Tableau轻松迁移到Power BI》。但小编了解到&#xff0c;如今有些企业更愿意选择国产BI平台。为此&#xff0c;小编今天以Fine BI为例子&#xff0c;介绍如何从Tableau轻松、低成本地迁移到国产BI平台。 在信创政策全面推进的背景下&#xff0c;企业数…...

蓝桥与力扣刷题(蓝桥 蓝桥骑士)

题目&#xff1a;小明是蓝桥王国的骑士&#xff0c;他喜欢不断突破自我。 这天蓝桥国王给他安排了 N 个对手&#xff0c;他们的战力值分别为 a1,a2,...,an&#xff0c;且按顺序阻挡在小明的前方。对于这些对手小明可以选择挑战&#xff0c;也可以选择避战。 身为高傲的骑士&a…...

前端学习笔记--CSS

HTMLCSSJavaScript 》 结构 表现 交互 如何学习 1.CSS是什么 2.CSS怎么用&#xff1f; 3.CSS选择器&#xff08;重点&#xff0c;难点&#xff09; 4.美化网页&#xff08;文字&#xff0c;阴影&#xff0c;超链接&#xff0c;列表&#xff0c;渐变。。。&#xff09; 5…...

阶段一:Java基础语法

目标&#xff1a;掌握Java的基本语法&#xff0c;理解变量、数据类型、运算符、控制结构等。 1. Java开发环境搭建 安装JDK配置环境变量编写第一个Java程序 代码示例&#xff1a; // HelloWorld.java public class HelloWorld { // 定义类名为 HelloWorldpublic static vo…...

31天Python入门——第15天:日志记录

你好&#xff0c;我是安然无虞。 文章目录 日志记录python的日志记录模块创建日志处理程序并配置输出格式将日志内容输出到控制台将日志写入到文件 logging更简单的一种使用方式 日志记录 日志记录是一种重要的应用程序开发和维护技术, 它用于记录应用程序运行时的关键信息和…...

深度学习框架PyTorch——从入门到精通(10)PyTorch张量简介

这部分是 PyTorch介绍——YouTube系列的内容&#xff0c;每一节都对应一个youtube视频。&#xff08;可能跟之前的有一定的重复&#xff09; 创建张量随机张量和种子张量形状张量数据类型 使用PyTorch张量进行数学与逻辑运算简单介绍——张量广播关于张量更多的数学操作原地修改…...

前端批量导入方式

webpack批量导入 webpack中使用 require.context 实现自动导入 const files require.context(./modules, false, /\.ts$/); const modules {}; files.keys().forEach((key) > {if (key ./index.ts) { return; }modules[key.replace(/(\.\/|\.ts)/g, )] files(key).def…...

使用ucharts写的小程序,然后让圆环中间的空白位置变大

将ringWidth属性调小 extra: { ring: { ringWidth: 20, activeOpacity: 1.5, activeRadius: 10, offsetAngle: 0, labelWidth: 15, border: true, borderWidth: 0, borderColor: #F…...

GPT-4o Image

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…...

SpringMVC请求与响应深度解析:从核心原理到高级实践

一、SpringMVC架构与核心组件剖析 SpringMVC是基于Java的MVC设计模型实现的轻量级Web框架&#xff0c;其核心架构围绕前端控制器模式构建。以下是核心组件及其作用&#xff1a; DispatcherServlet 作为前端控制器&#xff0c;所有请求首先到达此处。它负责请求分发、协调组件协…...

大模型量化框架GPTQModel的基本使用方法

接上一篇博客&#xff1a;AutoGPTQ报torch._C._LinAlgError: linalg.cholesky: The factorization could not be completed的解决办法-CSDN博客 如果Llama factory量化一直报错&#xff0c;可以改用其他的量化框架&#xff0c;例如GPTQ&#xff1a;https://github.com/ModelCl…...

C++:函数(通识版)

一、函数的基础 1.什么是函数&#xff1f;&#xff08;独立的功能单位&#xff09; 函数是C中封装代码逻辑的基本单元&#xff0c;用于执行特定任务。 作用&#xff1a;代码复用、模块化、提高可读性。 2、函数的基本结构 返回类型 函数名(参数列表) {// 函数体return 返回值…...

Spring AI相关的面试题

以下是150道Spring AI相关的面试题目及答案&#xff1a; ### Spring AI基础概念类 **1. 什么是Spring AI&#xff1f;** Spring AI是Spring框架的扩展&#xff0c;旨在简化人工智能模型在Java应用中的集成与使用&#xff0c;提供与Spring生态无缝衔接的工具和抽象&#xff0c…...

无线安灯按钮盒汽车零部件工厂的故障告警与人员调度专家

在汽车零部件制造领域&#xff0c;生产线故障与物料短缺等问题往往引发连锁反应&#xff0c;导致停机损失与成本激增。传统人工巡检与纸质工单模式已难以满足高效生产需求&#xff0c;而无线安灯按钮盒的智能化应用&#xff0c;正成为破解这一难题的关键利器。 一、精准告警&am…...