安卓13启动流程分析Android13

安卓通过bootloader加载到系统后,首先通过rc文件,启动系统服务

init.rc 复制代码
  service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
  socket zygote stream 666

rc文件中,首先启动了primary_zygote,使用app_process启动

注意:安卓中的zygote有三个称呼,分别是zygote,zygote_secondary,primary_zygote

安卓源码中,用zygote等价于primary_zygote,而zygote_secondary是另一种

primary_zygote通过fork产生system_server后,变为zygote_secondary

D:\AOSP\android-13.0.0_r9\frameworks\base\cmds\app_process\app_main.cpp

cpp 复制代码
class AppRuntime : public AndroidRuntime
{
public:
    AppRuntime(char* argBlockStart, const size_t argBlockLength)
        : AndroidRuntime(argBlockStart, argBlockLength)
        , mClass(NULL){}
    String8 mClassName;
    Vector<String8> mArgs;
    jclass mClass;
};
int main(int argc, char* const argv[])
{
    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
    maybeCreateDalvikCache();
    if (zygote) {
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    }
}

D:\AOSP\android-13.0.0_r9\frameworks\base\core\jni\AndroidRuntime.cpp

cpp 复制代码
// 开始安卓运行时,这里会启动虚拟机,并调用className传入的java类的main方法
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
    ALOGD(">>>>>> START %s uid %d <<<<<<\n",
            className != NULL ? className : "(unknown)", getuid());

    static const String8 startSystemServer("start-system-server");
    // 判断是primary_zygote还是zygote
    bool primary_zygote = false;

    /*
     * 'startSystemServer == true' means runtime is obsolete and not run from
     * init.rc anymore, so we print out the boot start event here.
     */
    // 说实话这段注释我看的不是很懂
    for (size_t i = 0; i < options.size(); ++i) {
        if (options[i] == startSystemServer) {
            primary_zygote = true;
           ...
        }
    }

    const char* rootDir = getenv("ANDROID_ROOT");
    if (rootDir == NULL) {
        rootDir = "/system";
        setenv("ANDROID_ROOT", rootDir, 1);
    }

    const char* artRootDir = getenv("ANDROID_ART_ROOT");
    // i18n是Internationalization,也就是国际化支持
    const char* i18nRootDir = getenv("ANDROID_I18N_ROOT");
    // tz是TimeZone,也就是时区
    const char* tzdataRootDir = getenv("ANDROID_TZDATA_ROOT");

    //const char* kernelHack = getenv("LD_ASSUME_KERNEL");
    //ALOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack);

    /* start the virtual machine */
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    JNIEnv* env;
    if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) {
        return;
    }
    onVmCreated(env);

    // 注册android的functions
    startReg(env);

    // 把class_name和option_string包装传入java的mian
    jclass stringClass;
    jobjectArray strArray;
    jstring classNameStr;

    stringClass = env->FindClass("java/lang/String");
    strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);
    classNameStr = env->NewStringUTF(className);
    env->SetObjectArrayElement(strArray, 0, classNameStr);

    for (size_t i = 0; i < options.size(); ++i) {
        jstring optionsStr = env->NewStringUTF(options.itemAt(i).c_str());
        assert(optionsStr != NULL);
        env->SetObjectArrayElement(strArray, i + 1, optionsStr);
    }

    // 启动虚拟机。同时当前线程将会变成虚拟机的主线程,知道虚拟机退出时才返回。
    char* slashClassName = toSlashClassName(className != NULL ? className : "");
    jclass startClass = env->FindClass(slashClassName);
    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 {
        env->CallStaticVoidMethod(startClass, startMeth, strArray);
    }
    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");
}

转到了java层

ZygoteInit

D:\AOSP\android-13.0.0_r9\frameworks\base\core\java\com\android\internal\os\ZygoteInit.java

java 复制代码
	/**
	* 这是Zygote进程的入口,在这里会创建Zygote服务,加载资源,处理和启动应用有关的任务。
	* 这个进程将会以-20的优先级(最高)运行,因此新进程的所有路径都需要将优先级设置为默认值
	* 或者在指向任何非系统代码前终止。
	* native端在SpecializeCommon中修改,而java端在ZygoteInit.handleSystemServerProcess,
	* ZygoteConnection.handleChildProc, and Zygote.childMain.
	*/
    @UnsupportedAppUsage
    public static void main(String[] argv) {
        ZygoteServer zygoteServer = null;

        // 设置标志位,当创建java线程时,如果是zygote则不创建。
        ZygoteHooks.startZygoteNoThreadCreation();

        // 将Zygote设置到他自己的进程组
        Os.setpgid(0, 0);

        Runnable caller;
        try {
            RuntimeInit.preForkInit();
            // 这个preForkInit中做了曾经的RuntimeInit.enableDdms
            // 同时调用MimeMap.setDefaultSupplier(DefaultMimeMapFactory::create);

            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]);
                }
            }

            final boolean isPrimaryZygote = zygoteSocketName.equals(Zygote.PRIMARY_SOCKET_NAME);
            // 懒加载模式下,不在这里加载资源和类
            if (!enableLazyPreload) {
                preload(bootTimingsTraceLog);
            }

            gcAndFinalize();

            Zygote.initNativeState(isPrimaryZygote);
            
            ZygoteHooks.stopZygoteNoThreadCreation();

            zygoteServer = new ZygoteServer(isPrimaryZygote);

            if (startSystemServer) {
                Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);

				// 当返回null时是父进程,返回不为null时,是system_server的入口
                if (r != null) {
                    r.run();
                    return;
                }
            }

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

            caller = zygoteServer.runSelectLoop(abiList);
        } catch (Throwable ex) {
            Log.e(TAG, "System zygote died with fatal 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();
        }
    }

创建zygoteServer,分化出system_server

  • 如果是system_server,则仅调用zygoteServer.closeServerSocket();
  • 如果是zygote_secondary,则调用zygoteServer.closeServerSocket();后,调用zygoteServer.runSelectLoop(abiList);

下面先看未分化前的步骤

Zygote.initNativeState

D:\AOSP\android-13.0.0_r9\frameworks\base\core\java\com\android\internal\os\Zygote.java

java 复制代码
	// 初始化Zygote的native状态,包括如下:
	// 1. 取出环境变量中的socket FDs
	// 2. 初始化安全属性
	// 3. 根据情况进行存储空间解挂载
	// 4. 加载必要的性能配置信息
    static void initNativeState(boolean isPrimary) {
        nativeInitNativeState(isPrimary);
    }

ZygoteServer

D:\AOSP\android-13.0.0_r9\frameworks\base\core\java\com\android\internal\os\ZygoteServer.java

java 复制代码
/**
 * zygote进程们的socket服务类
 */
class ZygoteServer {
    private LocalServerSocket mZygoteSocket;
    /**
    * USAP(Unspecialized App Process),这是安卓10(Q)引入的机制
    * 通过prefork的方式提前创建好一批进程,当有应用启动时,直接将已经创建好的进程分配给它
    * 省去了fork的动作,因此可以提升性能
    */
    private final LocalServerSocket mUsapPoolSocket;

    ZygoteServer(boolean isPrimaryZygote) {
        // 调用nativeGetUsapPoolEventFD,将fd转为java的FileDescriptor
        mUsapPoolEventFD = Zygote.getUsapPoolEventFD();

        if (isPrimaryZygote) {
            // Zygote.PRIMARY_SOCKET_NAME = "zygote"
            mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.PRIMARY_SOCKET_NAME);
            // Zygote.USAP_POOL_PRIMARY_SOCKET_NAME = "usap_pool_primary"
            mUsapPoolSocket =
                    Zygote.createManagedSocketFromInitSocket(
                            Zygote.USAP_POOL_PRIMARY_SOCKET_NAME);
        } else {
            mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.SECONDARY_SOCKET_NAME);
            mUsapPoolSocket =
                    Zygote.createManagedSocketFromInitSocket(
                            Zygote.USAP_POOL_SECONDARY_SOCKET_NAME);
        }

        mUsapPoolSupported = true;
        fetchUsapPoolPolicyProps();
    }
}

对于Zygote.getUsapPoolEventFD

Zygote.createManagedSocketFromInitSocket
java 复制代码
	// 使用init.rc中指定的fd来创建LocalServerSocket对象
	// 在init.rc中指定的fd,他的名字可以在system/core/rootdir中找到。同时这个fd也会绑定到/dev/sockets/目录下,fd在值会以ANDROID_SOCKET_<socketName>形式共享到环境变量中。
    static LocalServerSocket createManagedSocketFromInitSocket(String socketName) {
        int fileDesc;
        final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;

        try {
            String env = System.getenv(fullSocketName);
            fileDesc = Integer.parseInt(env);
        } catch (RuntimeException ex) {
            throw new RuntimeException("Socket unset or invalid: " + fullSocketName, ex);
        }

        try {
            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);
        }
    }

重量级forkSystemServer

D:\AOSP\android-13.0.0_r9\frameworks\base\core\java\com\android\internal\os\ZygoteInit.java

java 复制代码
	// 相当于unix的fork,当返回null时是父进程,返回不为null时,是system_server的入口
    private static Runnable forkSystemServer(String abiList, String socketName,
            ZygoteServer zygoteServer) {
        long capabilities = posixCapabilitiesAsBits(
                OsConstants.CAP_IPC_LOCK,
                OsConstants.CAP_KILL,
                OsConstants.CAP_NET_ADMIN,
                OsConstants.CAP_NET_BIND_SERVICE,
                OsConstants.CAP_NET_BROADCAST,
                OsConstants.CAP_NET_RAW,
                OsConstants.CAP_SYS_MODULE,
                OsConstants.CAP_SYS_NICE,
                OsConstants.CAP_SYS_PTRACE,
                OsConstants.CAP_SYS_TIME,
                OsConstants.CAP_SYS_TTY_CONFIG,
                OsConstants.CAP_WAKE_ALARM,
                OsConstants.CAP_BLOCK_SUSPEND
        );
        // 删掉一些不可用的'能力'Capabilities
        StructCapUserHeader header = new StructCapUserHeader(
                OsConstants._LINUX_CAPABILITY_VERSION_3, 0);
        StructCapUserData[] data;
        try {
            data = Os.capget(header);
        } catch (ErrnoException ex) {
            throw new RuntimeException("Failed to capget()", ex);
        }
        capabilities &= Integer.toUnsignedLong(data[0].effective) |
                (Integer.toUnsignedLong(data[1].effective) << 32);

        // 硬编码启动system
        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,3005,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",
        };
        ZygoteArguments parsedArgs;

        int pid;

        try {
            ZygoteCommandBuffer commandBuffer = new ZygoteCommandBuffer(args);
            try {
                parsedArgs = ZygoteArguments.getInstance(commandBuffer);
            } catch (EOFException e) {
                throw new AssertionError("Unexpected argument error for forking system server", e);
            }
            commandBuffer.close();
            Zygote.applyDebuggerSystemProperty(parsedArgs);
            Zygote.applyInvokeWithSystemProperty(parsedArgs);

            // 实际调用并返回int pid = nativeForkSystemServer();
            // Thread.currentThread().setPriority(Thread.NORM_PRIORITY);
            pid = Zygote.forkSystemServer(
                    parsedArgs.mUid, parsedArgs.mGid,
                    parsedArgs.mGids,
                    parsedArgs.mRuntimeFlags,
                    null,
                    parsedArgs.mPermittedCapabilities,
                    parsedArgs.mEffectiveCapabilities);
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException(ex);
        }

        // 实际上就是unix的fork,但是在这里进行了Runnable的映射
        // pid为0表示子进程,即system_server进程
        if (pid == 0) {
            if (hasSecondZygote(abiList)) {
                // 注意此时socketName是"zygote"
                waitForSecondaryZygote(socketName);
            }
            // 在ZygoteInit的main中,也会关闭一次,不用担心,ZygoteServer内部会判断是否已经关闭
            zygoteServer.closeServerSocket();
            return handleSystemServerProcess(parsedArgs);
        }

        return null;
    }
    private static void waitForSecondaryZygote(String socketName) {
        String otherZygoteName = Zygote.PRIMARY_SOCKET_NAME.equals(socketName)
                ? Zygote.SECONDARY_SOCKET_NAME : Zygote.PRIMARY_SOCKET_NAME;
        ZygoteProcess.waitForConnectionToZygote(otherZygoteName);
    }

	// 完成fork成system_server前的最后工作
    private static Runnable handleSystemServerProcess(ZygoteArguments parsedArgs) {
        // set umask to 0077 so new files and directories will default to owner-only permissions.
        Os.umask(S_IRWXG | S_IRWXO);
        // niceName被作为进程的名称
        if (parsedArgs.mNiceName != null) {
            Process.setArgV0(parsedArgs.mNiceName);
        }

        final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
		//上面forkSystemServer方法中定义的启动参数没有"--invoke-with",所以这里执行的是else分支
        if (parsedArgs.mInvokeWith != null) {
            String[] args = parsedArgs.mRemainingArgs;
            if (systemServerClasspath != null) {
                String[] amendedArgs = new String[args.length + 2];
                amendedArgs[0] = "-cp";
                amendedArgs[1] = systemServerClasspath;
                System.arraycopy(args, 0, amendedArgs, 2, args.length);
                args = amendedArgs;
            }

            WrapperInit.execApplication(parsedArgs.mInvokeWith,
                    parsedArgs.mNiceName, parsedArgs.mTargetSdkVersion,
                    VMRuntime.getCurrentInstructionSet(), null, args);

            throw new IllegalStateException("Unexpected return from WrapperInit.execApplication");
        } else {
            ClassLoader cl = getOrCreateSystemServerClassLoader();
            if (cl != null) {
                Thread.currentThread().setContextClassLoader(cl);
            }

            /*
             * Pass the remaining arguments to SystemServer.
             */
            return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
                    parsedArgs.mDisabledCompatChanges,
                    parsedArgs.mRemainingArgs, cl);
        }

        /* should never reach here */
    }
ZygoteProcess.waitForConnectionToZygote

D:\AOSP\android-13.0.0_r9\frameworks\base\core\java\android\os\ZygoteProcess.java

java 复制代码
    // 不断尝试连接Zygote,直到超时
    public static void waitForConnectionToZygote(String zygoteSocketName) {
        final LocalSocketAddress zygoteSocketAddress =
                new LocalSocketAddress(zygoteSocketName, LocalSocketAddress.Namespace.RESERVED);
        waitForConnectionToZygote(zygoteSocketAddress);
    }
    public static void waitForConnectionToZygote(LocalSocketAddress zygoteSocketAddress) {
        for (int n = numRetries; n >= 0; n--) {
            try {
                final ZygoteState zs =
                        ZygoteState.connect(zygoteSocketAddress, null);
                zs.close();
                return;
            } catch (IOException ioe) {
            }
            Thread.sleep(ZYGOTE_CONNECT_RETRY_DELAY_MS);
        }
    }
	// ZygoteState是ZygoteProcess内部类
    private static class ZygoteState implements AutoCloseable {
        static ZygoteState connect(@NonNull LocalSocketAddress zygoteSocketAddress,
                @Nullable LocalSocketAddress usapSocketAddress)
                throws IOException {

            DataInputStream zygoteInputStream;
            BufferedWriter zygoteOutputWriter;
            final LocalSocket zygoteSessionSocket.connect(zygoteSocketAddress);

            return new ZygoteState(zygoteSocketAddress, usapSocketAddress,
                                   zygoteSessionSocket, zygoteInputStream, zygoteOutputWriter,
                                   getAbiList(zygoteOutputWriter, zygoteInputStream));
        }
    }
ZygoteInit.zygoteInit
java 复制代码
    public static Runnable zygoteInit(int targetSdkVersion, long[] disabledCompatChanges,
            String[] argv, ClassLoader classLoader) {
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
        RuntimeInit.redirectLogStreams();

        RuntimeInit.commonInit();
        ZygoteInit.nativeZygoteInit();
        return RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv,
                classLoader);
    }
RuntimeInit.applicationInit

D:\AOSP\android-13.0.0_r9\frameworks\base\core\java\com\android\internal\os\RuntimeInit.java

java 复制代码
    protected static Runnable applicationInit(int targetSdkVersion, long[] disabledCompatChanges,
            String[] argv, ClassLoader classLoader) {
        // If the application calls System.exit(), terminate the process
        // immediately without running any shutdown hooks.  It is not possible to
        // shutdown an Android application gracefully.  Among other things, the
        // Android runtime shutdown hooks close the Binder driver, which can cause
        // leftover running threads to crash before the process actually exits.
        nativeSetExitWithoutCleanup(true);

        VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
        VMRuntime.getRuntime().setDisabledCompatChanges(disabledCompatChanges);

        final Arguments args = new Arguments(argv);

        // The end of of the RuntimeInit event (see #zygoteInit).
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

        // Remaining arguments are passed to the start class's static main
        return findStaticMain(args.startClass, args.startArgs, classLoader);
    }

    protected static Runnable findStaticMain(String className, String[] argv,
            ClassLoader classLoader) {
        Class<?> cl = Class.forName(className, true, classLoader);

        Method m = cl.getMethod("main", new Class[] { String[].class });

        return new MethodAndArgsCaller(m, argv);
    }

Runnable r.run()

启动system_server

zygoteServer.runSelectLoop

zygote准备接受请求

相关推荐
吾即是光4 分钟前
[SWPUCTF 2021 新生赛]error
android
大耳猫19 分钟前
Android 基于Camera2 API进行摄像机图像预览
android·kotlin·相机·camera
MYBOYER22 分钟前
Kotlin DSL Gradle 指南
android·开发语言·kotlin
Mr_Xuhhh1 小时前
程序地址空间
android·java·开发语言·数据库
呆呆小雅3 小时前
C# 结构体
android·java·c#
ᥬ 小月亮5 小时前
Layui表格的分页下拉框新增“全部”选项
android·javascript·layui
sunly_14 小时前
Flutter:启动屏逻辑处理02:启动页
android·javascript·flutter
Sgq丶15 小时前
Android Studio 配置 proto
android·ide·android studio
_小马快跑_19 小时前
ConstraintLayout 中的ImageFilterView探索:处理图片圆角、亮度、饱和度、图片重叠等
android
IT-sec19 小时前
jquery-picture-cut 任意文件上传(CVE-2018-9208)
android·前端·javascript·安全·web安全·网络安全·jquery