ZygoteInit从c到java

1.Android启动流程

image.png

2.init.cpp

// system\core\init\init.cpp
int main(int argc, char** argv) {
  ...
  // 创建虚拟文件
  mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755");
  mkdir("/dev/pts", 0755);
  mkdir("/dev/socket", 0755);
  ...
  // 属性服务
  property_init();
  start_property_service()
  ...
  // 解析init.rc文件
  Parser& parser = Parser::GetInstance();
  parser.AddSectionParser("service",std::make_unique<ServiceParser>());
  parser.AddSectionParser("on", std::make_unique<ActionParser>());
  parser.AddSectionParser("import", std::make_unique<ImportParser>());
  parser.ParseConfig("/init.rc");
}

相关知识点:

  • tmpfs,devpts,proc,sysfs 4类虚拟文件系统
  • property_service
  • SELinux SEAndroid安全机制
  • init.rc脚本文件

3.init.rc文件

init.rc是一个配置文件,内部由Android初始化语言编写(Android Init Language)编写的脚本,主要包含五种类型语句:Action、Command、Service、Option和Import。

import /init.${ro.zygote}.rc
因为Android5.0以后支持64位程序,为了相互兼容,所以${ro.zygote}会根据具体情况,被替换成zygote32.rczygote32_64.rczygote64.rczygote64_32.rc,区别是启动32位程序还是64位。其中32_64表示app_process32为主模式。

// 进程名称zygote
// 对应二进制文件/system/bin/app_process64
// 参数
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
    class main
    socket zygote 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
    writepid /dev/cpuset/foreground/tasks

zygote对应的二进制文件是 /system/bin/app_process64,
对应的目录在platform/frameworks/base/cmds/app_process/Android.mk,

include $(CLEAR_VARS)

LOCAL_SRC_FILES:= \
    app_main.cpp

LOCAL_SHARED_LIBRARIES := \
    libcutils \
    libutils \
    liblog \
    libbinder \
    libandroid_runtime \
    $(app_process_common_shared_libs) \

LOCAL_WHOLE_STATIC_LIBRARIES := libsigchain

LOCAL_LDFLAGS := -ldl -Wl,--version-script,art/sigchainlib/version-script.txt -Wl,--export-dynamic
LOCAL_CPPFLAGS := -std=c++11

LOCAL_MODULE := app_process__asan
LOCAL_MULTILIB := both
LOCAL_MODULE_STEM_32 := app_process32
LOCAL_MODULE_STEM_64 := app_process64

4.app_main.cpp

int main(int argc, char* const argv[])
{
     // 1.AppRuntime对象
    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
    
    // 2.解析参数
    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) { //需要启动SystemServer
            startSystemServer = true;
        } else if (strcmp(arg, "--application") == 0) { //表示是application启动模式,也就是普通应用程序
            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) { // 如果是zygote启动模式,则加载ZygoteInit
        // 3.start
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    } 

app_main.cpp的main方法主要做的事情:

  • 初始化AppRuntime;
  • 解析命令中参数;
  • 通过AppRuntime去启动ZygoteInit类

相关知识点:
init.rc启动一些重要的进程,每一个都是重要的知识点,比如

  • Service Manager管理binder进程通信
  • SufaceFlinger图形显示

5.void AndroidRuntime::start();

void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
    ... 
    /* start the virtual machine */
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL); //初始化JNI,加载libart.so
    JNIEnv* env;
    if (startVm(&mJavaVM, &env, zygote) != 0) { // 创建虚拟机
        return;
    }
    onVmCreated(env); // 表示虚拟创建完成

    /*
     * Register android functions.
     */
    if (startReg(env) < 0) { // 注册JNI函数
        ALOGE("Unable to register all android natives\n");
        return;
    }
    ... 
    // JNI方式调用ZygoteInit类的main函数
    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).string());
        assert(optionsStr != NULL);
        env->SetObjectArrayElement(strArray, i + 1, optionsStr);
    }

    /*
     * Start VM.  This thread becomes the main thread of the VM, and will
     * not return until the VM exits.
     */
    char* slashClassName = toSlashClassName(className);
    jclass startClass = env->FindClass(slashClassName);
  
    // 找到要启动的java类,然后调用其main方法
    jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
            "([Ljava/lang/String;)V");

     env->CallStaticVoidMethod(startClass, startMeth, strArray);
...

相关知识点:

  • jni基础知识及实现原理
  • 虚拟机(内存布局、垃圾回收、线程机制、指令优化等)

5.1 JniInvocation::Init()

bool JniInvocation::Init(const char* library) {
#ifdef __ANDROID__
  char buffer[PROP_VALUE_MAX];
#else
  char* buffer = NULL;
#endif
  library = GetLibrary(library, buffer);
  // Load with RTLD_NODELETE in order to ensure that libart.so is not unmapped when it is closed.
  // This is due to the fact that it is possible that some threads might have yet to finish
  // exiting even after JNI_DeleteJavaVM returns, which can lead to segfaults if the library is
  // unloaded.
  const int kDlopenFlags = RTLD_NOW | RTLD_NODELETE;
  handle_ = dlopen(library, kDlopenFlags);
  if (handle_ == NULL) {
    if (strcmp(library, kLibraryFallback) == 0) {
      // Nothing else to try.
      ALOGE("Failed to dlopen %s: %s", library, dlerror());
      return false;
    }
    // Note that this is enough to get something like the zygote
    // running, we can't property_set here to fix this for the future
    // because we are root and not the system user. See
    // RuntimeInit.commonInit for where we fix up the property to
    // avoid future fallbacks. http://b/11463182
    ALOGW("Falling back from %s to %s after dlopen error: %s",
          library, kLibraryFallback, dlerror());
    library = kLibraryFallback;
    handle_ = dlopen(library, kDlopenFlags);
    if (handle_ == NULL) {
      ALOGE("Failed to dlopen %s: %s", library, dlerror());
      return false;
    }
  }
  if (!FindSymbol(reinterpret_cast<void**>(&JNI_GetDefaultJavaVMInitArgs_),
                  "JNI_GetDefaultJavaVMInitArgs")) {
    return false;
  }
  if (!FindSymbol(reinterpret_cast<void**>(&JNI_CreateJavaVM_),
                  "JNI_CreateJavaVM")) {
    return false;
  }
  if (!FindSymbol(reinterpret_cast<void**>(&JNI_GetCreatedJavaVMs_),
                  "JNI_GetCreatedJavaVMs")) {
    return false;
  }
  return true;
}

5.2 startVm

int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote)
{
    JavaVMInitArgs initArgs;
    ...
    addOption("exit", (void*) runtime_exit); // 将参数放入mOptions数组中
    ...
    initArgs.version = JNI_VERSION_1_4;
    initArgs.options = mOptions.editArray();// 将mOptions赋值给initArgs
    initArgs.nOptions = mOptions.size();
    if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) { // 调用libart.so的JNI_CreateJavaVM函数
            ALOGE("JNI_CreateJavaVM failed\n");
            return -1;
    }
    return 0;
}

各种系统属性中读取一些参数,设置到AndroidRuntime的mOptions集合中存起来。
然后调用之前从libart.so中找到JNI_CreateJavaVM函数,并传入参数。

5.3 startReg(env)

/*static*/ int AndroidRuntime::startReg(JNIEnv* env)
{
    ...
    // 调用register_jni_procs进行JNI注册
    if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
        env->PopLocalFrame(NULL);
        return -1;
    }
    env->PopLocalFrame(NULL);

    return 0;
}

static 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) {
            return -1;
        }
    }
    return 0;
}

static const RegJNIRec gRegJNI[] = {
    REG_JNI(register_com_android_internal_os_RuntimeInit),
    REG_JNI(register_android_os_SystemClock),
    REG_JNI(register_android_util_EventLog),
    REG_JNI(register_android_util_Log),
    REG_JNI(register_android_util_MemoryIntArray),
    ...
};

6. ZygoteInit.java

上面appRuntime::start()启动虚拟机,通过jni调用ZygoteInit的main();ZygoteInit是c到java的入口,也是java的第一个进程,看一下main()的具体实现:

// frameworks\base\core\java\com\android\internal\os
public static void main(String argv[]) {
          ...
            boolean startSystemServer = false;
            String socketName = "zygote";
            String abiList = null;
            for (int i = 1; i < argv.length; i++) {
                if ("start-system-server".equals(argv[i])) {
                    startSystemServer = true;   // 需要启动system server
                } else if (argv[i].startsWith(ABI_LIST_ARG)) {
                    abiList = argv[i].substring(ABI_LIST_ARG.length());
                } else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
                    socketName = argv[i].substring(SOCKET_NAME_ARG.length());
                } else {
                    throw new RuntimeException("Unknown command line argument: " + argv[i]);
                }
            }

            if (abiList == null) {
                throw new RuntimeException("No ABI list supplied.");
            }
            
            // 建立一个socket连接服务端
            registerZygoteSocket(socketName);
            Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "ZygotePreload");
            
            // 预加载各类资源
            preload();
            ...
            // 由init.rc文件中配置的参数传递而来
            if (startSystemServer) {
                 // 开启系统服务
         startSystemServer(abiList, socketName);
            }
            // 进入循环等待ams通过socket通信来fork新的进程
            runSelectLoop(abiList);
            closeServerSocket();
    }

main方法中主要做了:

  • 建立socket服务端
  • 启动各种系统服务如ams,wms,pms...
  • 进入死循环,等待和处理ams通过socket传递的请求。

疑问点:既然android自身的binder能实现进程间通信,效率又高,为什么这里却选用socket,而不使用更好的binder,有什么限制吗?

7.runSelectLoop(abiList);

private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
        ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
        ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();

        fds.add(sServerSocket.getFileDescriptor());
        peers.add(null); // 保持fds索引一致

        // 进入死循环,通过socket的accept会进入阻塞状态
        while (true) {
            StructPollfd[] pollFds = new StructPollfd[fds.size()];
            for (int i = 0; i < pollFds.length; ++i) {
                pollFds[i] = new StructPollfd();
                pollFds[i].fd = fds.get(i);
                pollFds[i].events = (short) POLLIN;
            }
            try {
                Os.poll(pollFds, -1);
            } catch (ErrnoException ex) {
                throw new RuntimeException("poll failed", ex);
            }
            for (int i = pollFds.length - 1; i >= 0; --i) {
                if ((pollFds[i].revents & POLLIN) == 0) {
                    continue;
                }
                if (i == 0) {
                    // == 0 时 获取请求,有的话加入list中,下一次循环走入else中进行任务执行
                    ZygoteConnection newPeer = acceptCommandPeer(abiList);
                    peers.add(newPeer);
                    fds.add(newPeer.getFileDesciptor());
                } else {
                    // 处理请求
                    boolean done = peers.get(i).runOnce();
                    if (done) {
                        peers.remove(i);
                        fds.remove(i);
                    }
                }
            }
        }
    }

7.1 ZygoteConnection.runOnce()

boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
  ...
  fd = ZygoteInit.getServerSocketFileDescriptor();
  pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,...);

  if (pid == 0) {
     // 创建了新的进程,则运行程序本身的代码  pid>0表示父进程,<0表示fork失败
     handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
     return true;
  } else {
      return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);
  }

7.1.1 forkAndSpecialize()

runOnce()方法中的Zygote.forkAndSpecialize()是fork出子进程的方法
大致的步骤如下:

  • VM_HOOKS.preFork();调用dalvik_system_ZygoteHooks.cc源文件的preFork()做准备工作;
  • nativeForkAndSpecialize()本地方法,内部调用ForkAndSpecializeCommon(),这里才是linux的fork进程的具体实现,完成后再调用Zyogte的callPostForkChildHooks()回到java程序代码。
  • VM_HOOKS.postForkCommon();
private static final ZygoteHooks VM_HOOKS = new ZygoteHooks();
public static int forkAndSpecialize(int uid, int gid, int[] gids, int debugFlags,
          int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
          String instructionSet, String appDataDir) {
        // VM_HOOKS 在libcore\dalvik\src\main\java\dalvik\system下
        // 对应的源文件在 art\runtime\native\dalvik_system_ZygoteHooks.cc
        VM_HOOKS.preFork();
        // native方法 具体实现在com_android_internal_os_zygote_nativeForkAndSpecialize
        int pid = nativeForkAndSpecialize(
                  uid, gid, gids, debugFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
                  instructionSet, appDataDir);
        // Enable tracing as soon as possible for the child process.
        if (pid == 0) {
            Trace.setTracingEnabled(true);

            // Note that this event ends at the end of handleChildProc,
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork");
        }
        VM_HOOKS.postForkCommon();
        return pid;
    }

    private static void callPostForkChildHooks(int debugFlags, boolean isSystemServer,
            String instructionSet) {
        VM_HOOKS.postForkChild(debugFlags, isSystemServer, instructionSet);
    }

7.2 handleChildProc()

private void handleChildProc(Arguments parsedArgs,
  // 关闭子进程从Zygote fork过来的服务端socket
  closeSocket();
  ZygoteInit.closeServerSocket();
  ...

   if (parsedArgs.niceName != null) {   // 设置进程名称
      Process.setArgV0(parsedArgs.niceName);
   }

        if (parsedArgs.invokeWith != null) { // 没有传入--invoke-with,所以这里走的是else
            WrapperInit.execApplication(parsedArgs.invokeWith,
                    parsedArgs.niceName, parsedArgs.targetSdkVersion,
                    VMRuntime.getCurrentInstructionSet(),
                    pipeFd, parsedArgs.remainingArgs);
        } else {
            RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,
                    parsedArgs.remainingArgs, null /* classLoader */);
        }
    }

代码最后几行的条件语句,通过参数的invoke-with来做判断,会走两个分支,两个分支的最终目的都是一样的,因为走到这里都是zygoteInitrunSelectLoop()走过来的,也就是我们开启的应用进程,不是startSystemServer,所以这里的分支最终目的是通过反射调用ActivityThreadmain方法,在虚拟机里的执行java程序代码。
下面7.3和7.4分别来详细看一下上面的else和if分支,一般都会走到else中,所以先看一下。

7.3 RuntimeInit.zygoteInit()

    public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller {
        if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");

        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "RuntimeInit");
        redirectLogStreams();

        commonInit();
        nativeZygoteInit();
        applicationInit(targetSdkVersion, argv, classLoader);
    }

主要看流程不求甚解,commonInit就不看了,直接看nativeZygoteInit,这个本地方法对应AndroidRuntime类的com_android_internal_os_RuntimeInit_nativeZygoteInit,最终调用app_main.cppAppRuntime类的onZygoteInit()

// frameworks\base\cmds\app_process\app_main.cpp
class AppRuntime : public AndroidRuntime
{
public:
virtual void onZygoteInit()
    {
        sp<ProcessState> proc = ProcessState::self();
        ALOGV("App process: starting thread pool.\n");
        proc->startThreadPool();
    }
}

startThreadPool主要是binder的一些操作

String8 name = makeBinderThreadName();
sp<Thread> t = new PoolThread(isMain);
t->run(name.string());

顺便理一下app_main.cpp中定义的类AppRuntimeAndroidRuntime的子类,
AndroidRuntime.cpp路径是frameworks\base\core\jniAndroidRuntime.h路径
frameworks\base\include\android_runtime
接下来主要看applicationInit();

7.3.1 applicationInit()

 private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller {
        nativeSetExitWithoutCleanup(true);

        // We want to be fairly aggressive about heap utilization, to avoid
        // holding on to a lot of memory that isn't needed.
        VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
        VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);

        final Arguments args;
        try {
            args = new Arguments(argv);
        } catch (IllegalArgumentException ex) {
            Slog.e(TAG, ex.getMessage());
            // let the process exit
            return;
        }

        // 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
        // startClass: 如果AMS通过socket传递过来的是ActivityThread
        // 如果是SystemServer 则com.android.server.SystemServer
        invokeStaticMain(args.startClass, args.startArgs, classLoader);
    }

private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller {
        ...
        cl = Class.forName(className, true, classLoader);
        m = cl.getMethod("main", new Class[] { String[].class });
        throw new ZygoteInit.MethodAndArgsCaller(m, argv);
    }

applicationInit->invokeStaticMain->throw new ZygoteInit.MethodAndArgsCaller;
可以看到通过抛个MethodAndArgsCaller异常来反射调用main();为什么抛异常方式去调用,其实应用程序出现异常时log,只有ZygoteInit.main
ZygoteInit$MethodAndArgsCaller.run,而没有中间我们走过的这些过程,看起来程序就是从ZygoteInit.main开始的一样,可能是为了让日志看起来更清晰一点,省去了中间的很多无用log。但9.0这块又有变化可参考

...
at java.lang.reflect.Method.invoke!(Native method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:738)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:628)

7.4 WrapperInit.execApplication()

    public static void execApplication(String invokeWith, String niceName,
            int targetSdkVersion, String instructionSet, FileDescriptor pipeFd,
            String[] args) {
        StringBuilder command = new StringBuilder(invokeWith);

        final String appProcess;
        if (VMRuntime.is64BitInstructionSet(instructionSet)) {
            appProcess = "/system/bin/app_process64";
        } else {
            appProcess = "/system/bin/app_process32";
        }
        command.append(' ');
        command.append(appProcess);

        command.append(" /system/bin --application");
        if (niceName != null) {
            command.append(" '--nice-name=").append(niceName).append("'");
        }
        command.append(" com.android.internal.os.WrapperInit ");
        command.append(pipeFd != null ? pipeFd.getInt$() : 0);
        command.append(' ');
        command.append(targetSdkVersion);
        Zygote.appendQuotedShellArgs(command, args);
        Zygote.execShell(command.toString());
    }

可以看出这种启动模式是通过拼接如同init.rc中启动server的字符串参数配置,最终调用Zygote.execShell(command.toString());会走到一开始的地方app_main::main(),只不过带了--application参数,回到app_main中来看

int main(int argc, char* const argv[])
{
if (zygote) {
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    } else if (className) {
        // 走这里,之前介绍过这个start(),会执行RuntimeInit的main
        runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
    } 
}

7.4.1 RuntimeInit.main()

    public static final void main(String[] argv) {
        enableDdms();
        if (argv.length == 2 && argv[1].equals("application")) {
            if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application");
            redirectLogStreams();
        } else {
            if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting tool");
        }

        commonInit();

        /*
         * Now that we're running in interpreted code, call back into native code
         * to run the system.
         */
         // 该本地方法在AndroidRuntime中,会调用子类AppRuntime的onStart()(app_main.cpp中)
         // start()调用callMain,执行
        nativeFinishInit();

        if (DEBUG) Slog.d(TAG, "Leaving RuntimeInit!");
    }
// AndroidRuntime.cpp
static void com_android_internal_os_RuntimeInit_nativeFinishInit(JNIEnv* env, jobject clazz)
{
    gCurRuntime->onStarted();
}

  // 子类appRuntime的onStarted()
  virtual void onStarted()
    {
        sp<ProcessState> proc = ProcessState::self();
        ALOGV("App process: starting thread pool.\n");
        proc->startThreadPool();

        AndroidRuntime* ar = AndroidRuntime::getRuntime();
        ar->callMain(mClassName, mClass, mArgs);

        IPCThreadState::self()->stopProcess();
    }

callMain的实现过程就是反射调用ActivityThreadmain();

8. startSystemServer()

private static boolean startSystemServer(String abiList, String socketName)
            throws MethodAndArgsCaller, RuntimeException {
...
        String args[] = {
            "--setuid=1000",
            "--setgid=1000",
            "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1032,3001,3002,3003,3006,3007,3009,3010",
            "--capabilities=" + capabilities + "," + capabilities,
            "--nice-name=system_server",
            "--runtime-args",
            "com.android.server.SystemServer",
        };
pid = Zygote.forkSystemServer(
                    parsedArgs.uid, parsedArgs.gid,
                    parsedArgs.gids,
                    parsedArgs.debugFlags,
                    null,
                    parsedArgs.permittedCapabilities,
                    parsedArgs.effectiveCapabilities);
}
 if (pid == 0) { // 0表示子进程,大于0表示父进程,小于0表示fork失败
            if (hasSecondZygote(abiList)) {
                waitForSecondaryZygote(socketName);
            }

            handleSystemServerProcess(parsedArgs);
        }
        // 方法结束,走到上面的runSelectLoop中
        return true;

8.1 Zygote.forkSystemServer

    public static int forkSystemServer(int uid, int gid, int[] gids, int debugFlags,
            int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
        VM_HOOKS.preFork();
        int pid = nativeForkSystemServer(
                uid, gid, gids, debugFlags, rlimits, permittedCapabilities, effectiveCapabilities);
        // Enable tracing as soon as we enter the system_server.
        if (pid == 0) {
            Trace.setTracingEnabled(true);
        }
        VM_HOOKS.postForkCommon();
        return pid;
    }

forkSystemServer->con_android_internal_os_Zygote.ForkAndSpecializeCommon()
ForkAndSpecializeCommon中有调用了forkAndSpecialize()上面分析runSelectLoop()也走到这里,linux的fork前后操作不说了。

8.2 handleSystemServerProcess()

 private static void handleSystemServerProcess(
            ZygoteConnection.Arguments parsedArgs)
            throws ZygoteInit.MethodAndArgsCaller {
        // system-server进程同样不需要想zygote进程那样需要socket。
        closeServerSocket();

       ...
        if (systemServerClasspath != null) {
            performSystemServerDexOpt(systemServerClasspath);
        }

        if (parsedArgs.invokeWith != null) {
            String[] args = parsedArgs.remainingArgs;
            if (systemServerClasspath != null) {
                String[] amendedArgs = new String[args.length + 2];
                amendedArgs[0] = "-cp";
                amendedArgs[1] = systemServerClasspath;
                System.arraycopy(parsedArgs.remainingArgs, 0, amendedArgs, 2, parsedArgs.remainingArgs.length);
            }

            WrapperInit.execApplication(parsedArgs.invokeWith,
                    parsedArgs.niceName, parsedArgs.targetSdkVersion,
                    VMRuntime.getCurrentInstructionSet(), null, args);
        } else {
            ClassLoader cl = null;
            if (systemServerClasspath != null) {
                cl = createSystemServerClassLoader(systemServerClasspath,
                                                   parsedArgs.targetSdkVersion);

                Thread.currentThread().setContextClassLoader(cl);
            }
            
            RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
        }
    }

RuntimeInit.zygoteInit在上面也讲到过,重点是方法里面的applicationInit(targetSdkVersion, argv, classLoader);argv是第8节刚开始的那段代码里的,其中最后一个是com.android.server.SystemServer
这里就反射调用了SystemServer的main方法;

9.SystemServer.main()

main方法中初始化一个SystemServer对象(它自己),并且调用了自己的run();

private void run() {
  ...
  SystemProperties.set("persist.sys.dalvik.vm.lib.2", VMRuntime.getRuntime().vmLibrary());
  Looper.prepareMainLooper();  // loop对象
  // SystemServiceManager对象
  mSystemServiceManager = new SystemServiceManager(mSystemContext);
  LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
  ...
  startBootstrapServices(); // 优先级最高的最核心的一部分services 比如AMS
  startCoreServices();
  startOtherServices();
  Looper.loop(); // loop起来
}

9.1 startOtherServices()

该方法也是启动一些service,代码超级长1000多行的方法,只看重点

private void startOtherServices() {
  // 所有服务开启完成
  mActivityManagerService.systemReady(new Runnable() {
  })
};

所有系统服务开启完成后调用systemReady,判断activity栈中有没有对象,如果是null,开启第一个应用进程Launcher,然后就是startActivityForResult()->AMS通过socket通知Zygote进程fork,就是上面的runSelectLoop();关于AMS这块的Activity启动流程又是一个比较重要的流程。

知识点:

  • Activity启动流程

10. 总结

一句话总结:init进程启动第一个java进程zygote,接着zygote fork出SystemServer进程并启动相关服务,服务启动完成启动Launcher应用进程。

如果你刚刚才开始了解启动流程这部分内容,一定要有耐心一步一步去跟踪源码看下去,涉及到众多知识点,不懂可以先记录下来,以后逐个突破。Android启动的流程个人感觉是比较重要也是相对比较容易的一部分系统源码(流程容易,具体实现肯定不简单),启动的流程能够把很多知识点串联起来,搞清楚这块内容,为后面我们想进一步了解Android系统源码打下根基,清楚系统的大致轮廓。

最后附上两张大神制作的类图和时序图
Android启动流程类图.png
Android启动流程时序图.png

参考博客、书籍:
Android启动篇 — init原理(二)
Android启动流程简析
图解Android - Zygote, System Server 启动分析
邓凡平《深入理解Android Java虚拟机ART》
林学森《深入理解Android内核设计思想》

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350

推荐阅读更多精彩内容