首页 > 其他分享 >Android 11 Zygote启动流程

Android 11 Zygote启动流程

时间:2024-03-15 12:30:35浏览次数:24  
标签:11 -- ...... system Zygote zygote 进程 Android parsedArgs

Zygote 进程由init进程启动,是systemserver 进程和APP 进程的父进程
先看一下rc文件,以init.zygote32.rc为例

service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
    class main
    priority -20
    user root
    group root readproc reserved_disk
    socket zygote stream 660 root system
    socket usap_pool_primary stream 660 root system
    onrestart exec_background - system system -- /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
    writepid /dev/cpuset/foreground/tasks

其实就是执行 /system/bin/app_process ,传入“-Xzygote /system/bin --zygote --start-system-server” 参数。 /system/bin/app_process是由frameworks\base\cmds\app_process\app_main.cpp 编译得到的,所以执行 /system/bin/app_process 就是执行app_main.cpp 的main函数

//frameworks\base\cmds\app_process\app_main.cpp
int main(int argc, char* const argv[])
{
    //......

    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
    // Process command line arguments
    // ignore argv[0]
    //忽略-Xzygote参数
    argc--;
    argv++;
    
	//......
	//遍历参数
	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;
        }
    }
    //经过上面的遍历,zygote 为true,startSystemServer 为true
    Vector<String8> args;
	
	//......
        // We're in zygote mode.
        maybeCreateDalvikCache();

        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为true
    if (zygote) {
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    } else if (className) {
        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.");
    }

主要就是解析参数,根据传入的参数,构造args,单后调用runtime的start函数。 runtime是AppRuntime 对象,继承 AndroidRuntime,调用runtime的start函数,即调动到其父类AndroidRuntime类中start函数

//frameworks\base\core\jni\AndroidRuntime.cpp
//注意这里传入的className为com.android.internal.os.ZygoteInit
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
   //......
   	/* 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.
     */
    if (startReg(env) < 0) { //注册JNI函数,后续要添加自己的JNI文件的话,可以参考这个函数里面的实现
        ALOGE("Unable to register all android natives\n");
        return;
    }
	//......
	char* slashClassName = toSlashClassName(className != NULL ? 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"); //找到ZygoteInit的main方法
        if (startMeth == NULL) {
            ALOGE("JavaVM unable to find main() in '%s'\n", className);
            /* keep going */
        } else {
            env->CallStaticVoidMethod(startClass, startMeth, strArray);//执行main方法

	//......
	

在start函数中,主要做了以下工作:

  1. 启动虚拟机
  2. 注册JNI函数
  3. 执行ZygoteInit的main方法
//frameworks\base\core\java\com\android\internal\os\ZygoteInit.java
@UnsupportedAppUsage
    public static void main(String argv[]) {
        ZygoteServer zygoteServer = null;
        
        /*1,设置参数*/
         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])) {
                    startSystemServer = true;
                } else if ("--enable-lazy-preload".equals(argv[i])) {
                    enableLazyPreload = true;
                } else if (argv[i].startsWith(ABI_LIST_ARG)) {
                    abiList = argv[i].substring(ABI_LIST_ARG.length());
                } else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
                    zygoteSocketName = argv[i].substring(SOCKET_NAME_ARG.length());
                } else {
                    throw new RuntimeException("Unknown command line argument: " + argv[i]);
                }
           }
		
		//......
		
		/*2,预加载*/
		if (!enableLazyPreload) {
                bootTimingsTraceLog.traceBegin("ZygotePreload");
                EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
                        SystemClock.uptimeMillis());
                preload(bootTimingsTraceLog);
                EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
                        SystemClock.uptimeMillis());
                bootTimingsTraceLog.traceEnd(); // ZygotePreload
         }
		
		/*3,fork systemserver进程*/
		if (startSystemServer) {
                Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);

                // {@code r == null} in the parent (zygote) process, and {@code r != null} in the
                // child (system_server) process.
                if (r != null) {//4,启动systemserver进程
                    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.
            caller = zygoteServer.runSelectLoop(abiList);//5,等待APP请求创建进程
        } catch (Throwable ex) {
            Log.e(TAG, "System zygote died with exception", ex);
            throw ex;
        } 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();//创建成功,启动APP进程
        }

在main函数中主要做了以下工作:

  1. 预加载资源
  2. fork systemserver进程并启动
  3. 阻塞等待APP创建进程的请求,有请求的话,fork出APP进程

接下来看看Zygote是怎么创建出systemserver进程以及处理APP请求的,即分析forkSystemServer和runSelectLoop方法。systemserver进程的启动在分析systemserver的时候再分析。

forkSystemServer

//frameworks\base\core\java\com\android\internal\os\ZygoteInit.java
private static Runnable forkSystemServer(String abiList, String socketName,
            ZygoteServer zygoteServer) {
	
	//......
	 /* Hardcoded command line to start the system server */
	 /*注意最后一个参数是com.android.server.SystemServer*/
	String args[] = {
                "--setuid=1000",
                "--setgid=1000",
                "--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",
                "--capabilities=" + capabilities + "," + capabilities,
                "--nice-name=system_server",
                "--runtime-args",
                "--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
                "com.android.server.SystemServer",
        };
        ZygoteArguments parsedArgs = null;

        int pid;
        
        try {
        	//根据参数构造ZygoteArguments 
            parsedArgs = new ZygoteArguments(args);
            
            //......

            /* Request to fork the system server process */
            pid = Zygote.forkSystemServer(
                    parsedArgs.mUid, parsedArgs.mGid,
                    parsedArgs.mGids,
                    parsedArgs.mRuntimeFlags,
                    null,
                    parsedArgs.mPermittedCapabilities,
                    parsedArgs.mEffectiveCapabilities);
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException(ex);
        }
		
		/* For child process */
        if (pid == 0) {
            if (hasSecondZygote(abiList)) {
                waitForSecondaryZygote(socketName);
            }
            zygoteServer.closeServerSocket();
            //这里返回一个Runnable ,然后在ZygoteInit的main函数中调用此Runnable 的run方法,启动systemserver
            return handleSystemServerProcess(parsedArgs);
        }

        return null;
    }

先构造参数,然后调用Zygote的forkSystemServer方法。fork成功之后,如果是子线程,则返回一个Runnable

//frameworks\base\core\java\com\android\internal\os\Zygote.java
static int forkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,
            int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
        ZygoteHooks.preFork();

        int pid = nativeForkSystemServer(
                uid, gid, gids, runtimeFlags, rlimits,
                permittedCapabilities, effectiveCapabilities);

        // Set the Java Language thread priority to the default value for new apps.
        Thread.currentThread().setPriority(Thread.NORM_PRIORITY);

        ZygoteHooks.postForkCommon();
        return pid;
    }

继续调用nativeForkSystemServer方法,对应JNI的com_android_internal_os_Zygote_nativeForkSystemServer方法

//frameworks\base\core\jni\com_android_internal_os_Zygote.cpp
static jint com_android_internal_os_Zygote_nativeForkAndSpecialize(
        JNIEnv* env, jclass, jint uid, jint gid, jintArray gids,
        jint runtime_flags, jobjectArray rlimits,
        jint mount_external, jstring se_info, jstring nice_name,
        jintArray managed_fds_to_close, jintArray managed_fds_to_ignore, jboolean is_child_zygote,
        jstring instruction_set, jstring app_data_dir, jboolean is_top_app,
        jobjectArray pkg_data_info_list, jobjectArray whitelisted_data_info_list,
        jboolean mount_data_dirs, jboolean mount_storage_dirs) {

		//......

		pid_t pid = ForkCommon(env, false, fds_to_close, fds_to_ignore, true);

    if (pid == 0) {
      SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits,
                       capabilities, capabilities,
                       mount_external, se_info, nice_name, false,
                       is_child_zygote == JNI_TRUE, instruction_set, app_data_dir,
                       is_top_app == JNI_TRUE, pkg_data_info_list,
                       whitelisted_data_info_list,
                       mount_data_dirs == JNI_TRUE,
                       mount_storage_dirs == JNI_TRUE);
    }
    return pid;
}

static pid_t ForkCommon(JNIEnv* env, bool is_system_server,
                        const std::vector<int>& fds_to_close,
                        const std::vector<int>& fds_to_ignore,
                        bool is_priority_fork) {
		//......
		
		pid_t pid = fork();

		//......
}

可以看出,通过调用fork函数,fork出systemserver子进程

runSelectLoop

runSelectLoop对于Zygote进程来说,是一个死循环,利用poll机制,没事件的时候就阻塞等待

Runnable runSelectLoop(String abiList) {
        ArrayList<FileDescriptor> socketFDs = new ArrayList<>();
        ArrayList<ZygoteConnection> peers = new ArrayList<>();

        socketFDs.add(mZygoteSocket.getFileDescriptor());
        peers.add(null);

        mUsapPoolRefillTriggerTimestamp = INVALID_TIMESTAMP;

        while (true) {
			//......

			try {
                pollReturnValue = Os.poll(pollFDs, pollTimeoutMs);
            } catch (ErrnoException ex) {
                throw new RuntimeException("poll failed", ex);
            }
			
			//.......
		}

有事件请求,调用processOneCommand,如果是创建子进程的请求,就创建子进程,并在子进程中返回一个Runnable,供ZygoteInit去启动子进程(注意:父进程即Zygote还是在运行,并不会返回退出)

		//......
		final Runnable command = connection.processOneCommand(this);

      	// TODO (chriswailes): Is this extra check necessary?
       	if (mIsForkChild) {
       		// We're in the child. We should always have a command to run at
        	// this stage if processOneCommand hasn't called "exec".
        	if (command == null) {
        		throw new IllegalStateException("command == null");
        	}

       	return command;
       	//......

在processOneCommand方法中调用forkAndSpecialize ,创建子进程

Runnable processOneCommand(ZygoteServer zygoteServer) {
	//......

	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.mWhitelistedDataInfoList,
                parsedArgs.mBindMountAppDataDirs, parsedArgs.mBindMountAppStorageDirs);

	 try {
            if (pid == 0) {
                // in child
                zygoteServer.setForkChild();

                zygoteServer.closeServerSocket();
                IoUtils.closeQuietly(serverPipeFd);
                serverPipeFd = null;

                return handleChildProc(parsedArgs, childPipeFd, parsedArgs.mStartChildZygote);

	//......
}

后面也是和fork systemserver进程一样,进入JNI,通过调用fork,创建子进程。所以zogyte的runSelectLoop方法,就是监听客户端事件,如果客户端请求创建进程,则fork出子进程。

总结
Zygote进程启动过程中,主要做了以下事情

  1. 启动虚拟机
  2. 注册JNI函数
  3. 预加载资源
  4. fork 出 systemserver进程并去启动它
  5. 等待客户端的请求,如果客户端请求创建进程,则fork进程并去启动它

另外,Android 11 Zygote 可支持使用线程池创建子进程,来优化应用的启动速度。参考Zygote pre-fork线程池源码分析

标签:11,--,......,system,Zygote,zygote,进程,Android,parsedArgs
From: https://blog.csdn.net/littleyards/article/details/136651283

相关文章

  • 浮木云学习日志(11)---表格设计(一)
    ​表格作为展现数据最为清晰、高效的形式之一,同时又具有复用度高,拓展性强优势,是最常见的信息展示形式,也是对数据进行浏览和操作最便捷的设计方式,合理的表格设计能给用户带来高效的信息获取率。今天我就利用浮木云软件设计开发平台https://www.fumucloud.com/设计一款简洁美观的......
  • Android NDK入门:在应用中加入C和C++的力量
    目录​编辑引NDK的设计目的与Java/Kotlin的结合使用场景开发流程设置项目以支持NDK编写本地代码使用JNI连接本地代码和Java/Kotlin代码编译和运行你的应用附 引自诩方向是android方向的移动端开发工程师,却从来没有真正仔细了解过NDK,这里就详细的整理了解一下n......
  • 在 Android 上恢复已删除文件的 5 种简单方法
    您可能会因为意外删除、未完成的Android更新、手机意外关机等原因而丢失Android上的重要数据。新技术的发展使许多手机功能或程序能够从内部恢复丢失的数据。在Android上恢复已删除文件的5种简单方法然而恢复成功率的不确定性也成为人们克服数据丢失困境的重要考虑......
  • Android中的NFC操作
    目录1.申请权限2.设置意图过滤器3.判断NFC功能是否可用(NfcAdapter)4.NFC感应(NfcAdapter)启用与禁用5.NFC数据解码6.案例代码一览NFC的全称是“NearFieldCommunication”,意思是近场通信、与邻近的区域通信。该功能由NfcAdapter(NFC适配器)控制。1.申请权限<!--N......
  • 信息学奥赛一本通:1146:判断字符串是否为回文
    【题目描述】输入一个字符串,输出该字符串是否回文。回文是指顺读和倒读都一样的字符串。【输入】输入为一行字符串(字符串中没有空白字符,字符串长度不超过100)。【输出】如果字符串是回文,输出yes;否则,输出no。【输入样例】abcdedcba【输出样例】yes【参考程序......
  • QT6.6下android编译及调用自定义so库方法
    一.问题概述   最近需要把QT程序从5.12的桌面环境移植到QT6.6的android下,项目中有很多DLL库要重新编译为so文件,移植到android环境然后调用,中间有很多坑,虽然大体和桌面系统用法相同,但细节上还是有区别的,尤其是so库的调用方法上,过程中也是debug了两天才解决,如果你也遇到了同......
  • powerbuilder11.5解析XML
    //定义变量OLEObjectlole_xmlhttpOLEObjectlole_xml//创建MSXML2.XMLHTTP对象lole_xmlhttp=CREATEOLEObjectlole_xmlhttp.ConnectToNewObject("MSXML2.XMLHTTP")//创建MSXML2.DOMDocument对象lole_xml=CREATEOLEObjectlole_xml.ConnectToNewObject("......
  • 代码随想录算法训练营第day17|110.平衡二叉树 、 257. 二叉树的所有路径 、404.左叶子
    目录a.110.平衡二叉树b.257.二叉树的所有路径 c.404.左叶子之和a.110.平衡二叉树力扣题目链接(opensnewwindow)给定一个二叉树,判断它是否是高度平衡的二叉树。本题中,一棵高度平衡二叉树定义为:一个二叉树每个节点的左右两个子树的高度差的绝对值不超过1。示例1......
  • android项目运行流程
    android项目运行流程三步 第一步:查清单AndroidManifest.xmlandroid项目核心在app的src的main里java是代码,res是资源有很多xml,然后AndroidManifest.xml是清单这是AndroidManifest.xml,在里面找到category.LAUNCHER-->里面的activity的名称就是我们要访问的第二步:跳到Main......
  • android App启动流程
    App启动流程分为2个部分,一个是系统开机,拉起LauncherAPP。另一个流程分为LauncherAPP点击桌面应用图标,然后启动APP。我们首先分析LauncherAPP的启动。LauncherAPP的启动:在android启动流程-SystemServer一篇文章中我们简单提过LauncherAPP启动的过程,本章我们具体分析一下L......