Android修炼系列(十五),一看就记住的系统启动流程

一起学源码(1):系统启动流程

这是“一起学源码”系列的第一篇文章,坚持就是胜利,共勉。

1.png

引导程序

引导程序是Android系统运行前的小程序,并不是Android操作系统的一部分,它需要针对特定主板和芯片。引导程序是OEM厂商或运行商进行加锁、限制的地方。

内核启动

Android内核启动方式类似桌面linux,主要步骤见下:

  1. 设置缓存
  2. 被保护存储器
  3. 计划列表
  4. 加载驱动

init.rc

init是Android系统的第一个进程(PID = 0),它通过解析init.rc脚本来启动其他系统服务进程,如 Zygote,SystemService,ServiceManager。

我们说的 init.rc 是一个脚本文件,它有着自己的一系列语法规则,本文不做细究, 规范可参考:/system/core/init/Readme.txt,栗子可参考下文的init.zygote64.rc文件。

Zygote

Zygote是由init解析init.rc脚本时启动的。Android系统可根据 ro.zygote 的具体值,按需加载32位或64位机器的描述Zygote.rc。

# system/core/rootdir/init.rc
import /init.${ro.zygote}.rc
复制代码

zygote.png

其中init.zygote64.rc 见下:

#name     此service名称:zygote
#pathname service所在路径:/system/bin/app_process64
#argument 启动service所带参数:-Xzygote /system/bin --zygote --start-system-server
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
    #所属classmain,而非core
    class main
    priority -20
    #在启动服务前,将服务切换至root,默认情况用户都是root
    user root
    group root readproc reserved_disk
    #创建一个/dev/socket/zygotesocket,并将它的fd值传递给启动它的init进程
    socket zygote stream 660 root system
    socket usap_pool_primary stream 660 root system
    #当此服务重启时,执行如下指令
    onrestart write /sys/android_power/request_state wake
    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
复制代码

从zygote的path可以看出,zygote所在的程序叫app_process64。

4.png

app_process

app_process 的源码路径在 /frameworks/base/cmds/app_pocess 中,主函数 app_main.cpp 部分代码见下:

#if defined(__LP64__)
static const char ABI_LIST_PROPERTY[] = "ro.product.cpu.abilist64";
static const char ZYGOTE_NICE_NAME[] = "zygote64";

int main(int argc, char* const argv[])
{
    ...
    #argv[]就是init传进的-Xzygote /system/bin --zygote --start-system-server
    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
    argv++;
    ...
    #a参数解析
    bool zygote = false;
    bool startSystemServer = false;
    bool application = false;
    String8 niceName;
    String8 className;
    ++i;
    while (i < argc) {
        const char* arg = argv[i++];
        if (strcmp(arg, "--zygote") == 0) {
            #b当前进程用来承载zygote
            zygote = true;
            #c更改进程别名为: zygote64
            niceName = ZYGOTE_NICE_NAME;
        } else if (strcmp(arg, "--start-system-server") == 0) {
            #d启动system server
            startSystemServer = true;
        } else if (strcmp(arg, "--application") == 0) {
            #e启动进入独立的程序模式
            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;
        }
    }
    ...
    if (zygote) {
        #runtime启动ZygoteInit
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    } else if (className) {
        runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
    } else {
        ...
    }
}
复制代码

5.png

这里的runtime是AppRuntime对象,详见下:

AppRuntime

源码位于 /frameworks/base/core/jni/AndroidRuntime.cpp ,部分代码见下:

void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
    ...
    #a启动虚拟机,并根据Android属性来设置虚拟机的参数
    if (startVm(&mJavaVM, &env, zygote) != 0) {
        return;
    }
    #b虚拟机启动后回调
    onVmCreated(env);
    #c JNI方法注册
    if (startReg(env) < 0) {
        ALOGE("Unable to register all android natives\n");
        return;
    }
    ...
    jclass stringClass;
    jobjectArray strArray;
    jstring classNameStr;
    ...
    #d 这里className即在app_process传入的“com.android.internal.os.ZygoteInit”
    #e 将className转换为"com/android/internal/os/ZygoteInit"
    char* slashClassName = toSlashClassName(className != NULL ? className : "");
    jclass startClass = env->FindClass(slashClassName);
    
    #f 判空
    ...
    #g 反射调用ZygoteInit的main方法,之后ZygoteInit会运行在虚拟机上
    jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
            "([Ljava/lang/String;)V");
    env->CallStaticVoidMethod(startClass, startMeth, strArray);
    #h 释放相应对象的内存空间
    free(slashClassName);
    ...
}
复制代码

17.png

ZygoteInit

源码位于 /frameworks/base/core/java/com/android/internal/os/ZygoteInit.java , 部分代码见下:

public static void main(String argv[]) {
    ...
    try {
        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 server
                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 (abiList == null) {
            throw new RuntimeException("No ABI list supplied.");
        }
            
        if (!enableLazyPreload) {
            ...
            // 如果app_process的调用参数argv[]不带有“–enable-lazy-preload”
            // 则会通此方法直接预加载虚拟机运行时所需要的各类资源
            preload(bootTimingsTraceLog);
            ...
        } else {
            Zygote.resetNicePriority();
        }
        ...
        // GC操作
        bootTimingsTraceLog.traceBegin("PostZygoteInitGC");
        gcAndFinalize();
        ...
        // 创建一个Socket接口,Socket接口是通过文件描述符控制的
        zygoteServer = new ZygoteServer(isPrimaryZygote);
        if (startSystemServer) {
            // 创建一个新的进程来启动各种系统服务
            Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
            if (r != null) {
                r.run();
                return;
            }
        }
        Log.i(TAG, "Accepting command socket connections");
        // 这是一个while死循环,作为zygote的守护体存在
        caller = zygoteServer.runSelectLoop(abiList);
    }
    ...
}
复制代码

6.png

forkSystemServer 方法会创建一个新的进程来启动各种系统服务,此方法稍后再说。我们先来看下另一个核心方法runSelectLoop,这是一个while死循环,除非Zygote退出或者出现异常,否则不会跳出循环。部分代码见下:

Runnable runSelectLoop(String abiList) {
    ArrayList<FileDescriptor> socketFDs = new ArrayList<FileDescriptor>();
    ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
    // 获取上面Socket的文件描述符,并添加到ArrayList<FileDescriptor>的集合里
    socketFDs.add(mZygoteSocket.getFileDescriptor());
    // 添加null是为了保持fds和peers的一致性,对应的是Zygote Server Socket这个监听者
    peers.add(null);
    while (true) {
        ...
        boolean usapPoolFDRead = false;
        while (--pollIndex >= 0) {
            // 当接收到客户端发出连接请求 或数据处理请求到来,则往下执行;
            // 否则进入continue,跳出本次循环。
            if ((pollFDs[pollIndex].revents & POLLIN) == 0) {
                continue;
            }
            if (pollIndex == 0) {
                // 有新的请求连接,通过此方法产生一个新的ZygoteConnection;
                // 然后分别更新peers和fds
                ZygoteConnection newPeer = acceptCommandPeer(abiList);
                peers.add(newPeer);
                socketFDs.add(newPeer.getFileDescriptor());
            } else if (pollIndex < usapPoolEventFDIndex) {
                // 已建立的连接中,有客户端发送过来的数据需要处理
                try {
                    ZygoteConnection connection = peers.get(pollIndex);
                    // 见下文
                    final Runnable command = connection.processOneCommand(this);
                    ...
                    } 
                ...
            } 
        ...
    }
}
复制代码

核心方法processOneCommand,通过方法内部的forkAndSpecialize方法,为每个新启动的应用程序生成自己独立的进程,并在handleChildProc方法中运行应用程序本身的代码:

Runnable processOneCommand(ZygoteServer zygoteServer) {
    ...
    // zygote为每个新启动的应用程序生成自己独立的进程
    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.mTargetSdkVersion);
    try {
       if (pid == 0) {
            // in child
            zygoteServer.setForkChild();
            zygoteServer.closeServerSocket();
            IoUtils.closeQuietly(serverPipeFd);
            serverPipeFd = null;
            // 进入子进程流程,通过此方法运行应用程序本身的代码
            return handleChildProc(parsedArgs, descriptors, childPipeFd,
                    parsedArgs.mStartChildZygote);
        } else {
            // 父进程中,pid<0表示故障
            IoUtils.closeQuietly(childPipeFd);
            childPipeFd = null;
            handleParentProc(pid, descriptors, serverPipeFd);
            return null;
        }
    } finally {
        IoUtils.closeQuietly(childPipeFd);
        IoUtils.closeQuietly(serverPipeFd);
    }
}

复制代码

7.png

再回到 ZygoteInit main 主函数代码。在 forkSystemServer 方法内通过 forkSystemServer 方法创建了一个新的进程,其中 “–setuid=1000” 代表进程 ID,“–nice-name=system_server”代表进程名称。而这个进程接下来会执行 handleSystemServerProcess 方法,来启动支撑系统运行的 System Server。

    private static Runnable forkSystemServer(String abiList, String socketName,
            ZygoteServer zygoteServer) {
        ...
        /* Hardcoded command line to start the system server */
        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",
                "--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 {
            // 用于解析参数,生成目标格式
            parsedArgs = new ZygoteArguments(args);
            Zygote.applyDebuggerSystemProperty(parsedArgs);
            Zygote.applyInvokeWithSystemProperty(parsedArgs);
            boolean profileSystemServer = SystemProperties.getBoolean(
                    "dalvik.vm.profilesystemserver", false);
            if (profileSystemServer) {
                parsedArgs.mRuntimeFlags |= Zygote.PROFILE_SYSTEM_SERVER;
            }
            // 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);
        }
        /* For child process */
        if (pid == 0) {
            if (hasSecondZygote(abiList)) {
                waitForSecondaryZygote(socketName);
            }
            // 关闭zygote原有的socket
            zygoteServer.closeServerSocket();
            return handleSystemServerProcess(parsedArgs);
        }
        return null;
    }
复制代码

在 handleSystemServerProcess 方法内,当 parsedArgs.mInvokeWith == null 时,会执行 ZygoteInit.zygoteInit 方法。

    private static Runnable handleSystemServerProcess(ZygoteArguments parsedArgs) {
        ...
        if (parsedArgs.mInvokeWith != null) {
            String[] args = parsedArgs.mRemainingArgs;
            ...
            WrapperInit.execApplication(parsedArgs.mInvokeWith,
                    parsedArgs.mNiceName, parsedArgs.mTargetSdkVersion,
                    VMRuntime.getCurrentInstructionSet(), null, args);
            throw new IllegalStateException("Unexpected return from WrapperInit.execApplication");
        } else {
            createSystemServerClassLoader();
            ClassLoader cl = sCachedSystemServerClassLoader;
            if (cl != null) {
                Thread.currentThread().setContextClassLoader(cl);
            }
            /*
             * Pass the remaining arguments to SystemServer.
             */
            return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
                    parsedArgs.mRemainingArgs, cl);
        }
        /* should never reach here */
    }
复制代码

9.png

这是 zygoteInit 的逻辑,redirectLogStreams 关闭 system.out 和 system.err ,并重定向到 android log。commonInit 处理了通用部分的初始化操作,nativeZygoteInit 是本地初始化函数,负责本地系统服务的启动,而在 JNI 机制中, Native 函数在 Java 层会有一个声明,然后在本地层得到真正的实现。可见下文的 SystemServer().run() 方法内的 System.loadLibrary(“android_servers”) :

 public static final Runnable zygoteInit(int targetSdkVersion, String[] argv,
            ClassLoader classLoader) {
        if (RuntimeInit.DEBUG) {
            Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");
        }
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
        RuntimeInit.redirectLogStreams();
        RuntimeInit.commonInit();
        ZygoteInit.nativeZygoteInit();
        return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
    }
复制代码

在applicationInit方法中args.startClass即上文说的forkSystemServer创建服务进程时的args内的 “com.android.server.SystemServer”,findStaticMain方法将会反射调用 args.startClass的main方法。

    protected static Runnable applicationInit(int targetSdkVersion, String[] argv,
            ClassLoader classLoader) {
        ...
        // 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;
        try {
            cl = Class.forName(className, true, classLoader);
        } catch (ClassNotFoundException ex) {
            throw new RuntimeException(
                    "Missing class when invoking static main " + className,
                    ex);
        }
        Method m;
        try {
            m = cl.getMethod("main", new Class[] { String[].class });
        } catch (NoSuchMethodException ex) {
            throw new RuntimeException(
                    "Missing static main on " + className, ex);
        } catch (SecurityException ex) {
            throw new RuntimeException(
                    "Problem getting static main on " + className, ex);
        }
        int modifiers = m.getModifiers();
        if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
            throw new RuntimeException(
                    "Main method is not public and static on " + className);
        }
        /*
         * This throw gets caught in ZygoteInit.main(), which responds
         * by invoking the exception's run() method. This arrangement
         * clears up all the stack frames that were required in setting
         * up the process.
         */
        return new MethodAndArgsCaller(m, argv);
    }
复制代码

这是 SystemServer 的 main 主函数,也就是 applicationInit 反射调用的方法,它又会直接调用 SystemServer().run() 方法来实现 java 层系统服务的启动。

    public static void main(String[] args) {
        new SystemServer().run();
    }
复制代码

11.png

在 run 方法中,准备主循环体,加载本地服务库到内存,并初始化本地服务,启动各种类型的 system server,通过 Looper.loop 进入长循环中,并依托 nativeZygoteInit 启动的 Binder 服务接受和处理外界请求。

    private void run() {
        try {
            ...
            if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
                Slog.w(TAG, "System clock is before 1970; setting to 1970.");
                SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
            }
            ...
            Looper.prepareMainLooper();
            Looper.getMainLooper().setSlowLogThresholdMs(
                    SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS);
            // Initialize native services.
            System.loadLibrary("android_servers");
            ...
            // Initialize the system context.
            createSystemContext();
            // Create the system service manager.
            mSystemServiceManager = new SystemServiceManager(mSystemContext);
            mSystemServiceManager.setStartInfo(mRuntimeRestart,
                    mRuntimeStartElapsedTime, mRuntimeStartUptime);
            LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
        } 
        ...
        // Start services.
        try {
            traceBeginAndSlog("StartServices");
            startBootstrapServices();
            startCoreServices();
            startOtherServices();
            SystemServerInitThreadPool.shutdown();
        }
        ...
        // Loop forever.
        Looper.loop();
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

复制代码

总结

看着时序图脑海里重新回顾一下吧,意图是串联,而不是死磕细节:

13.png

好了,本文到这里就结束了。如果本文对你有用,来点个赞吧,大家的肯定也是阿呆i坚持写作的动力。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享