美文网首页Android开发程序员程序员技术栈
Android系统启动之zyogte进程java(下)

Android系统启动之zyogte进程java(下)

作者: Lee_5566 | 来源:发表于2019-03-31 17:33 被阅读5次
    image.png

    目录

    第一篇:Android系统启动之bootloader
    第二篇:Android系统启动之Init流程(上)
    第三篇:Android系统启动之Init流程(下)
    第四篇:Android系统启动之init.rc文件解析过程
    第五篇:Android系统启动之zyogte进程
    第六篇:Android系统启动之zyogte进程java(上)
    第七篇:Android系统启动之zyogte进程java(下)

    ZygoteServer类

    ZygoteServer的代码路径frameworks/base/core/java/com/android/internal/os/ZygoteServer.java
    构造函数:

    ZygoteServer() {
    }
    

    构造函数中什么也不做.

    registerServerSocket函数

     /**
         * Registers a server socket for zygote command connections
         *
         * @throws RuntimeException when open fails
         */
        void registerServerSocket(String socketName) {
            if (mServerSocket == null) {
                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(fullSocketName + " unset or invalid", ex);
                }
    
                try {
                    FileDescriptor fd = new FileDescriptor();
                    fd.setInt$(fileDesc);
                    mServerSocket = new LocalServerSocket(fd);
                } catch (IOException ex) {
                    throw new RuntimeException(
                            "Error binding to local socket '" + fileDesc + "'", ex);
                }
            }
        }
    

    代码中实现了:

    1. 创建了一个FileDescriptor对象,并通过调用setInt$()方法来设置其值。
    2. 创建了LocalServerSocket对象,来创建本地的服务socket,并将其值保存在全局变量mServerSocket中。

    预加载系统类和资源

    为了加快应用程序的启动,Android把系统公用的Java类和一部分Framework的资源保存在zygote中了,这样就可以保证zygote进程fork子进程的是共享的。
    主要实现是函数preload

                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
                } else {
                    Zygote.resetNicePriority();
                }
    

    preload代码实现:

        static void preload(BootTimingsTraceLog bootTimingsTraceLog) {
            Log.d(TAG, "begin preload");
            bootTimingsTraceLog.traceBegin("BeginIcuCachePinning");
            beginIcuCachePinning();
            bootTimingsTraceLog.traceEnd(); // BeginIcuCachePinning
            bootTimingsTraceLog.traceBegin("PreloadClasses");
            preloadClasses();
            bootTimingsTraceLog.traceEnd(); // PreloadClasses
            bootTimingsTraceLog.traceBegin("PreloadResources");
            preloadResources();
            bootTimingsTraceLog.traceEnd(); // PreloadResources
            Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadOpenGL");
            preloadOpenGL();
            Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
            preloadSharedLibraries();
            preloadTextResources();
            // Ask the WebViewFactory to do any initialization that must run in the zygote process,
            // for memory sharing purposes.
            WebViewFactory.prepareWebViewInZygote();
            endIcuCachePinning();
            warmUpJcaProviders();
            Log.d(TAG, "end preload");
    
            sPreloadComplete = true;
        }
    

    其中包括:

    预加载 含义
    preloadClasses 对Java类的预加载
    preloadResources 对资源的预加载
    preloadOpenGL 对OpenGL的预加载
    preloadSharedLibraries, 对共享库的预加载
    preloadTextResources 对文本资源的预加载.
    WebViewFactory 对web端的预加载

    对Java类的预加载

    preloadClasses函数实现如下:

        /**
         * Performs Zygote process initialization. Loads and initializes
         * commonly used classes.
         *
         * Most classes only cause a few hundred bytes to be allocated, but
         * a few will allocate a dozen Kbytes (in one case, 500+K).
         */
        private static void preloadClasses() {
            final VMRuntime runtime = VMRuntime.getRuntime();
    
            InputStream is;
            try {
                is = new FileInputStream(PRELOADED_CLASSES);
            } catch (FileNotFoundException e) {
                Log.e(TAG, "Couldn't find " + PRELOADED_CLASSES + ".");
                return;
            }
    
            Log.i(TAG, "Preloading classes...");
            long startTime = SystemClock.uptimeMillis();
    
            // Drop root perms while running static initializers.
            final int reuid = Os.getuid();
            final int regid = Os.getgid();
    
            // We need to drop root perms only if we're already root. In the case of "wrapped"
            // processes (see WrapperInit), this function is called from an unprivileged uid
            // and gid.
            boolean droppedPriviliges = false;
            if (reuid == ROOT_UID && regid == ROOT_GID) {
                try {
                    Os.setregid(ROOT_GID, UNPRIVILEGED_GID);
                    Os.setreuid(ROOT_UID, UNPRIVILEGED_UID);
                } catch (ErrnoException ex) {
                    throw new RuntimeException("Failed to drop root", ex);
                }
    
                droppedPriviliges = true;
            }
    
            // Alter the target heap utilization.  With explicit GCs this
            // is not likely to have any effect.
            float defaultUtilization = runtime.getTargetHeapUtilization();
            runtime.setTargetHeapUtilization(0.8f);
    
            try {
                BufferedReader br
                    = new BufferedReader(new InputStreamReader(is), 256);
    
                int count = 0;
                String line;
                while ((line = br.readLine()) != null) {
                    // Skip comments and blank lines.
                    line = line.trim();
                    if (line.startsWith("#") || line.equals("")) {
                        continue;
                    }
    
                    Trace.traceBegin(Trace.TRACE_TAG_DALVIK, line);
                    try {
                        if (false) {
                            Log.v(TAG, "Preloading " + line + "...");
                        }
                        // Load and explicitly initialize the given class. Use
                        // Class.forName(String, boolean, ClassLoader) to avoid repeated stack lookups
                        // (to derive the caller's class-loader). Use true to force initialization, and
                        // null for the boot classpath class-loader (could as well cache the
                        // class-loader of this class in a variable).
                        Class.forName(line, true, null);
                        count++;
                    } catch (ClassNotFoundException e) {
                        Log.w(TAG, "Class not found for preloading: " + line);
                    } catch (UnsatisfiedLinkError e) {
                        Log.w(TAG, "Problem preloading " + line + ": " + e);
                    } catch (Throwable t) {
                        Log.e(TAG, "Error preloading " + line + ".", t);
                        if (t instanceof Error) {
                            throw (Error) t;
                        }
                        if (t instanceof RuntimeException) {
                            throw (RuntimeException) t;
                        }
                        throw new RuntimeException(t);
                    }
                    Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
                }
    
                Log.i(TAG, "...preloaded " + count + " classes in "
                        + (SystemClock.uptimeMillis()-startTime) + "ms.");
            } catch (IOException e) {
                Log.e(TAG, "Error reading " + PRELOADED_CLASSES + ".", e);
            } finally {
                IoUtils.closeQuietly(is);
                // Restore default.
                runtime.setTargetHeapUtilization(defaultUtilization);
    
                // Fill in dex caches with classes, fields, and methods brought in by preloading.
                Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadDexCaches");
                runtime.preloadDexCaches();
                Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
    
                // Bring back root. We'll need it later if we're in the zygote.
                if (droppedPriviliges) {
                    try {
                        Os.setreuid(ROOT_UID, ROOT_UID);
                        Os.setregid(ROOT_GID, ROOT_GID);
                    } catch (ErrnoException ex) {
                        throw new RuntimeException("Failed to restore root", ex);
                    }
                }
            }
        }
    

    预加载类的步骤:
    1. 打开文件PRELOADED_CLASSES, PRELOADED_CLASSES的定义是PRELOADED_CLASSES = "/system/etc/preloaded-classes";.
    2. 使用BufferedReader对象,读取文件内容.
    3. 使用Class.forName函数加载类.

    对资源的预加载

    preloadResources函数实现如下

      /**
         * Load in commonly used resources, so they can be shared across
         * processes.
         *
         * These tend to be a few Kbytes, but are frequently in the 20-40K
         * range, and occasionally even larger.
         */
        private static void preloadResources() {
            final VMRuntime runtime = VMRuntime.getRuntime();
    
            try {
                mResources = Resources.getSystem();
                mResources.startPreloading();
                if (PRELOAD_RESOURCES) {
                    Log.i(TAG, "Preloading resources...");
    
                    long startTime = SystemClock.uptimeMillis();
                    TypedArray ar = mResources.obtainTypedArray(
                            com.android.internal.R.array.preloaded_drawables);
                    int N = preloadDrawables(ar);
                    ar.recycle();
                    Log.i(TAG, "...preloaded " + N + " resources in "
                            + (SystemClock.uptimeMillis()-startTime) + "ms.");
    
                    startTime = SystemClock.uptimeMillis();
                    ar = mResources.obtainTypedArray(
                            com.android.internal.R.array.preloaded_color_state_lists);
                    N = preloadColorStateLists(ar);
                    ar.recycle();
                    Log.i(TAG, "...preloaded " + N + " resources in "
                            + (SystemClock.uptimeMillis()-startTime) + "ms.");
    
                    if (mResources.getBoolean(
                            com.android.internal.R.bool.config_freeformWindowManagement)) {
                        startTime = SystemClock.uptimeMillis();
                        ar = mResources.obtainTypedArray(
                                com.android.internal.R.array.preloaded_freeform_multi_window_drawables);
                        N = preloadDrawables(ar);
                        ar.recycle();
                        Log.i(TAG, "...preloaded " + N + " resource in "
                                + (SystemClock.uptimeMillis() - startTime) + "ms.");
                    }
                }
                mResources.finishPreloading();
            } catch (RuntimeException e) {
                Log.w(TAG, "Failure preloading resources", e);
            }
        }
    

    加载资源的步骤:
    1. 使用Resources.getSystem函数获取一个Resources对象。该方法是一个androidSDK 公开的方法,但一般在应用开发中较少用到,因为该方法返回的是Resource对象仅能访问framework的资源
    2. 调用mResources.startPreloading函数和mResources.finishPreloading函数分别在开始和结束的时候重置加载标志mPreloading.
    3. 调用preloadDrawables函数和preloadColorStateLists函数分别加载rpreloaded_drawables、preloaded_color_state_lists中preloaded_freeform_multi_window_drawables定义的资源。

    对OpenGL的预加载

    preloadOpenGL代码如下:

    private static void preloadOpenGL() {
            String driverPackageName = SystemProperties.get(PROPERTY_GFX_DRIVER);
            if (!SystemProperties.getBoolean(PROPERTY_DISABLE_OPENGL_PRELOADING, false) &&
                    (driverPackageName == null || driverPackageName.isEmpty())) {
                EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
            }
        }
    

    PROPERTY_GFX_DRIVER宏定义:

    private static final String PROPERTY_GFX_DRIVER = "ro.gfx.driver.0";
    private static final String PROPERTY_DISABLE_OPENGL_PRELOADING = "ro.zygote.disable_gl_preload";
    

    加载OpenGL的步骤:

    1. 获取系统属性ro.gfx.driver.0
    2. 判断是否加载过
    3. 如果没有加载过,使用eglGetDisplay加载相应的库.

    eglGetDisplay函数实现frameworks/base/opengl/java/android/opengl/EGL14.java:

    public static final int EGL_DEFAULT_DISPLAY            = 0;
    // C function EGLDisplay eglGetDisplay ( EGLNativeDisplayType display_id )
    
    public static native EGLDisplay eglGetDisplay(
        int display_id
    );
    

    是native层实现的代码,

    对共享库的预加载

    preloadSharedLibraries代码如下:

        private static void preloadSharedLibraries() {
            Log.i(TAG, "Preloading shared libraries...");
            System.loadLibrary("android");
            System.loadLibrary("compiler_rt");
            System.loadLibrary("jnigraphics");
       
    

    加载了共享库:android、compiler_rt、jnigraphics.

    对文本资源的预加载.

    preloadTextResources代码如下:

        private static void preloadTextResources() {
            Hyphenator.init();
            TextView.preloadFontCache();
        }
    

    Hyphenator的静态函数init来完成文件初始化的.

    对web端的预加载

    prepareWebViewInZygote函数代码frameworks/base/core/java/android/webkit/WebViewFactory.java:

        /**
         * Perform any WebView loading preparations that must happen in the zygote.
         * Currently, this means allocating address space to load the real JNI library later.
         */
        public static void prepareWebViewInZygote() {
            try {
                System.loadLibrary("webviewchromium_loader");
                long addressSpaceToReserve =
                        SystemProperties.getLong(CHROMIUM_WEBVIEW_VMSIZE_SIZE_PROPERTY,
                        CHROMIUM_WEBVIEW_DEFAULT_VMSIZE_BYTES);
                sAddressSpaceReserved = nativeReserveAddressSpace(addressSpaceToReserve);
    
                if (sAddressSpaceReserved) {
                    if (DEBUG) {
                        Log.v(LOGTAG, "address space reserved: " + addressSpaceToReserve + " bytes");
                    }
                } else {
                    Log.e(LOGTAG, "reserving " + addressSpaceToReserve +
                            " bytes of address space failed");
                }
            } catch (Throwable t) {
                // Log and discard errors at this stage as we must not crash the zygote.
                Log.e(LOGTAG, "error preparing native loader", t);
            }
        }
    
    

    主要是加载对应的webviewchromium_loader库.

    启动SystemServer

    从一下代码开始,便开始启动SystemServer.

                if (startSystemServer) {
                    startSystemServer(abiList, socketName, zygoteServer);
                }
    

    startSystemServer函数实现:

       /**
         * Prepare the arguments and fork for the system server process.
         */
        private static boolean startSystemServer(String abiList, String socketName, ZygoteServer zygoteServer)
                throws Zygote.MethodAndArgsCaller, RuntimeException {
            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
            );
            /* Containers run without this capability, so avoid setting it in that case */
            if (!SystemProperties.getBoolean(PROPERTY_RUNNING_IN_CONTAINER, false)) {
                capabilities |= posixCapabilitiesAsBits(OsConstants.CAP_BLOCK_SUSPEND);
            }
            /* 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,1032,3001,3002,3003,3006,3007,3009,3010",
                "--capabilities=" + capabilities + "," + capabilities,
                "--nice-name=system_server",
                "--runtime-args",
                "com.android.server.SystemServer",
            };
            ZygoteConnection.Arguments parsedArgs = null;
    
            int pid;
    
            try {
                parsedArgs = new ZygoteConnection.Arguments(args);
                ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
                ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);
    
                /* Request to fork the system server process */
                pid = Zygote.forkSystemServer(
                        parsedArgs.uid, parsedArgs.gid,
                        parsedArgs.gids,
                        parsedArgs.debugFlags,
                        null,
                        parsedArgs.permittedCapabilities,
                        parsedArgs.effectiveCapabilities);
            } catch (IllegalArgumentException ex) {
                throw new RuntimeException(ex);
            }
    
            /* For child process */
            if (pid == 0) {
                if (hasSecondZygote(abiList)) {
                    waitForSecondaryZygote(socketName);
                }
    
                zygoteServer.closeServerSocket();
                handleSystemServerProcess(parsedArgs);
            }
    
            return true;
        }
    

    代码启动步骤:

    1. 为fork准备参数parsedArgs
    2. 调用Zygote.forkSystemServer()方法来创建system server
    3. 调用handleSystemServerProcess方法执行system_server的剩余工作

    forkSystemServer函数

    代码实现frameworks/base/core/java/com/android/internal/os/Zygote.java:

    
        /**
         * Special method to start the system server process. In addition to the
         * common actions performed in forkAndSpecialize, the pid of the child
         * process is recorded such that the death of the child process will cause
         * zygote to exit.
         *
         * @param uid the UNIX uid that the new process should setuid() to after
         * fork()ing and and before spawning any threads.
         * @param gid the UNIX gid that the new process should setgid() to after
         * fork()ing and and before spawning any threads.
         * @param gids null-ok; a list of UNIX gids that the new process should
         * setgroups() to after fork and before spawning any threads.
         * @param debugFlags bit flags that enable debugging features.
         * @param rlimits null-ok an array of rlimit tuples, with the second
         * dimension having a length of 3 and representing
         * (resource, rlim_cur, rlim_max). These are set via the posix
         * setrlimit(2) call.
         * @param permittedCapabilities argument for setcap()
         * @param effectiveCapabilities argument for setcap()
         *
         * @return 0 if this is the child, pid of the child
         * if this is the parent, or -1 on error.
         */
        public static int forkSystemServer(int uid, int gid, int[] gids, int debugFlags,
                int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
            VM_HOOKS.preFork();
            // Resets nice priority for zygote process.
            resetNicePriority();
            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;
        }
    

    注释很多,代码主要是调用native层的函数nativeForkSystemServer.

    nativeForkSystemServer函数代码实现frameworks/base/core/jni/com_android_internal_os_Zygote.cpp:

    
    static jint com_android_internal_os_Zygote_nativeForkSystemServer(
            JNIEnv* env, jclass, uid_t uid, gid_t gid, jintArray gids,
            jint debug_flags, jobjectArray rlimits, jlong permittedCapabilities,
            jlong effectiveCapabilities) {
      pid_t pid = ForkAndSpecializeCommon(env, uid, gid, gids,
                                          debug_flags, rlimits,
                                          permittedCapabilities, effectiveCapabilities,
                                          MOUNT_EXTERNAL_DEFAULT, NULL, NULL, true, NULL,
                                          NULL, NULL, NULL);
      if (pid > 0) {
          // The zygote process checks whether the child process has died or not.
          ALOGI("System server process %d has been created", pid);
          gSystemServerPid = pid;
          // There is a slight window that the system server process has crashed
          // but it went unnoticed because we haven't published its pid yet. So
          // we recheck here just to make sure that all is well.
          int status;
          if (waitpid(pid, &status, WNOHANG) == pid) {
              ALOGE("System server process %d has died. Restarting Zygote!", pid);
              RuntimeAbort(env, __LINE__, "System server process has died. Restarting Zygote!");
          }
      }
      return pid;
    }
    

    以上代码实现步骤:
    1. 创建子进程
    2. 如果System serve死亡,就重启Zygote.

    ForkAndSpecializeCommon函数

    ForkAndSpecializeCommond代码实现:

    / Utility routine to fork zygote and specialize the child process.
    static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGids,
                                         jint debug_flags, jobjectArray javaRlimits,
                                         jlong permittedCapabilities, jlong effectiveCapabilities,
                                         jint mount_external,
                                         jstring java_se_info, jstring java_se_name,
                                         bool is_system_server, jintArray fdsToClose,
                                         jintArray fdsToIgnore,
                                         jstring instructionSet, jstring dataDir) {
      SetSigChldHandler();
    
      sigset_t sigchld;
      sigemptyset(&sigchld);
      sigaddset(&sigchld, SIGCHLD);
    
      // Temporarily block SIGCHLD during forks. The SIGCHLD handler might
      // log, which would result in the logging FDs we close being reopened.
      // This would cause failures because the FDs are not whitelisted.
      //
      // Note that the zygote process is single threaded at this point.
      if (sigprocmask(SIG_BLOCK, &sigchld, nullptr) == -1) {
        ALOGE("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno));
        RuntimeAbort(env, __LINE__, "Call to sigprocmask(SIG_BLOCK, { SIGCHLD }) failed.");
      }
    
      // Close any logging related FDs before we start evaluating the list of
      // file descriptors.
      __android_log_close();
    
      // If this is the first fork for this zygote, create the open FD table.
      // If it isn't, we just need to check whether the list of open files has
      // changed (and it shouldn't in the normal case).
      std::vector<int> fds_to_ignore;
      FillFileDescriptorVector(env, fdsToIgnore, &fds_to_ignore);
      if (gOpenFdTable == NULL) {
        gOpenFdTable = FileDescriptorTable::Create(fds_to_ignore);
        if (gOpenFdTable == NULL) {
          RuntimeAbort(env, __LINE__, "Unable to construct file descriptor table.");
        }
      } else if (!gOpenFdTable->Restat(fds_to_ignore)) {
        RuntimeAbort(env, __LINE__, "Unable to restat file descriptor table.");
      }
    
      pid_t pid = fork();
    
      if (pid == 0) {
        // The child process.
        gMallocLeakZygoteChild = 1;
    
        // Set the jemalloc decay time to 1.
        mallopt(M_DECAY_TIME, 1);
    
        // Clean up any descriptors which must be closed immediately
        DetachDescriptors(env, fdsToClose);
    
        // Re-open all remaining open file descriptors so that they aren't shared
        // with the zygote across a fork.
        if (!gOpenFdTable->ReopenOrDetach()) {
          RuntimeAbort(env, __LINE__, "Unable to reopen whitelisted descriptors.");
        }
    
        if (sigprocmask(SIG_UNBLOCK, &sigchld, nullptr) == -1) {
          ALOGE("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno));
          RuntimeAbort(env, __LINE__, "Call to sigprocmask(SIG_UNBLOCK, { SIGCHLD }) failed.");
        }
    
        // Keep capabilities across UID change, unless we're staying root.
        if (uid != 0) {
          EnableKeepCapabilities(env);
        }
    
        SetInheritable(env, permittedCapabilities);
        DropCapabilitiesBoundingSet(env);
    
        bool use_native_bridge = !is_system_server && (instructionSet != NULL)
            && android::NativeBridgeAvailable();
        if (use_native_bridge) {
          ScopedUtfChars isa_string(env, instructionSet);
          use_native_bridge = android::NeedsNativeBridge(isa_string.c_str());
        }
        if (use_native_bridge && dataDir == NULL) {
          // dataDir should never be null if we need to use a native bridge.
          // In general, dataDir will never be null for normal applications. It can only happen in
          // special cases (for isolated processes which are not associated with any app). These are
          // launched by the framework and should not be emulated anyway.
          use_native_bridge = false;
          ALOGW("Native bridge will not be used because dataDir == NULL.");
        }
    
        if (!MountEmulatedStorage(uid, mount_external, use_native_bridge)) {
          ALOGW("Failed to mount emulated storage: %s", strerror(errno));
          if (errno == ENOTCONN || errno == EROFS) {
            // When device is actively encrypting, we get ENOTCONN here
            // since FUSE was mounted before the framework restarted.
            // When encrypted device is booting, we get EROFS since
            // FUSE hasn't been created yet by init.
            // In either case, continue without external storage.
          } else {
            RuntimeAbort(env, __LINE__, "Cannot continue without emulated storage");
          }
        }
    
        if (!is_system_server) {
            int rc = createProcessGroup(uid, getpid());
            if (rc != 0) {
                if (rc == -EROFS) {
                    ALOGW("createProcessGroup failed, kernel missing CONFIG_CGROUP_CPUACCT?");
                } else {
                    ALOGE("createProcessGroup(%d, %d) failed: %s", uid, pid, strerror(-rc));
                }
            }
        }
    
        SetGids(env, javaGids);
    
        SetRLimits(env, javaRlimits);
    
        if (use_native_bridge) {
          ScopedUtfChars isa_string(env, instructionSet);
          ScopedUtfChars data_dir(env, dataDir);
          android::PreInitializeNativeBridge(data_dir.c_str(), isa_string.c_str());
        }
    
        int rc = setresgid(gid, gid, gid);
        if (rc == -1) {
          ALOGE("setresgid(%d) failed: %s", gid, strerror(errno));
          RuntimeAbort(env, __LINE__, "setresgid failed");
        }
    
        rc = setresuid(uid, uid, uid);
        if (rc == -1) {
          ALOGE("setresuid(%d) failed: %s", uid, strerror(errno));
          RuntimeAbort(env, __LINE__, "setresuid failed");
        }
    
        if (NeedsNoRandomizeWorkaround()) {
            // Work around ARM kernel ASLR lossage (http://b/5817320).
            int old_personality = personality(0xffffffff);
            int new_personality = personality(old_personality | ADDR_NO_RANDOMIZE);
            if (new_personality == -1) {
                ALOGW("personality(%d) failed: %s", new_personality, strerror(errno));
            }
        }
    
        SetCapabilities(env, permittedCapabilities, effectiveCapabilities, permittedCapabilities);
    
        SetSchedulerPolicy(env);
    
        const char* se_info_c_str = NULL;
        ScopedUtfChars* se_info = NULL;
        if (java_se_info != NULL) {
            se_info = new ScopedUtfChars(env, java_se_info);
            se_info_c_str = se_info->c_str();
            if (se_info_c_str == NULL) {
              RuntimeAbort(env, __LINE__, "se_info_c_str == NULL");
            }
        }
        const char* se_name_c_str = NULL;
        ScopedUtfChars* se_name = NULL;
        if (java_se_name != NULL) {
            se_name = new ScopedUtfChars(env, java_se_name);
            se_name_c_str = se_name->c_str();
            if (se_name_c_str == NULL) {
              RuntimeAbort(env, __LINE__, "se_name_c_str == NULL");
            }
        }
        rc = selinux_android_setcontext(uid, is_system_server, se_info_c_str, se_name_c_str);
        if (rc == -1) {
          ALOGE("selinux_android_setcontext(%d, %d, \"%s\", \"%s\") failed", uid,
                is_system_server, se_info_c_str, se_name_c_str);
          RuntimeAbort(env, __LINE__, "selinux_android_setcontext failed");
        }
    
        // Make it easier to debug audit logs by setting the main thread's name to the
        // nice name rather than "app_process".
        if (se_info_c_str == NULL && is_system_server) {
          se_name_c_str = "system_server";
        }
        if (se_info_c_str != NULL) {
          SetThreadName(se_name_c_str);
        }
    
        delete se_info;
        delete se_name;
    
        UnsetSigChldHandler();
    
        env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, debug_flags,
                                  is_system_server, instructionSet);
        if (env->ExceptionCheck()) {
          RuntimeAbort(env, __LINE__, "Error calling post fork hooks.");
        }
      } else if (pid > 0) {
        // the parent process
    
        // We blocked SIGCHLD prior to a fork, we unblock it here.
        if (sigprocmask(SIG_UNBLOCK, &sigchld, nullptr) == -1) {
          ALOGE("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno));
          RuntimeAbort(env, __LINE__, "Call to sigprocmask(SIG_UNBLOCK, { SIGCHLD }) failed.");
        }
      }
      return pid;
    }
    

    以上代码实现步骤:

    1. 设置子进程的signal信号处理函数
    2. fork子进程
    3. 在子进程挂载external storage
    4. 在子进程设置用户Id、组Id和进程所属的组
    5. 在在进程执行系统调用setrlimit来设置进程的系统资源限制
    6. 在子进程调用SetCapabilities()函数并在其中执行系统调动系统调>capset来设置进程的权限
    7. 在子进程调用SetSchedulerPolicy()函数并在其中执行系统调动系统调set_sched_policy来设置调度策略
    8. 在子进程设置应用进程的安全上下文
    9. 回复signal信号处理函数
    10. 完成一些运行时后的工作

    handleSystemServerProcess函数

    handleSystemServerProcess代码实现frameworks/base/core/java/com/android/internal/os/ZygoteInit.java:

       /**
         * Finish remaining work for the newly forked system server process.
         */
        private static void handleSystemServerProcess(
                ZygoteConnection.Arguments parsedArgs)
                throws Zygote.MethodAndArgsCaller {
    
            // set umask to 0077 so new files and directories will default to owner-only permissions.
            Os.umask(S_IRWXG | S_IRWXO);
    
            if (parsedArgs.niceName != null) {
                Process.setArgV0(parsedArgs.niceName);
            }
    
            final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
            if (systemServerClasspath != null) {
                performSystemServerDexOpt(systemServerClasspath);
                // Capturing profiles is only supported for debug or eng builds since selinux normally
                // prevents it.
                boolean profileSystemServer = SystemProperties.getBoolean(
                        "dalvik.vm.profilesystemserver", false);
                if (profileSystemServer && (Build.IS_USERDEBUG || Build.IS_ENG)) {
                    try {
                        File profileDir = Environment.getDataProfilesDePackageDirectory(
                                Process.SYSTEM_UID, "system_server");
                        File profile = new File(profileDir, "primary.prof");
                        profile.getParentFile().mkdirs();
                        profile.createNewFile();
                        String[] codePaths = systemServerClasspath.split(":");
                        VMRuntime.registerAppInfo(profile.getPath(), codePaths);
                    } catch (Exception e) {
                        Log.wtf(TAG, "Failed to set up system server profile", e);
                    }
                }
            }
    
            if (parsedArgs.invokeWith != null) {
                String[] args = parsedArgs.remainingArgs;
                // If we have a non-null system server class path, we'll have to duplicate the
                // existing arguments and append the classpath to it. ART will handle the classpath
                // correctly when we exec a new process.
                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.invokeWith,
                        parsedArgs.niceName, parsedArgs.targetSdkVersion,
                        VMRuntime.getCurrentInstructionSet(), null, args);
            } else {
                ClassLoader cl = null;
                if (systemServerClasspath != null) {
                    cl = createPathClassLoader(systemServerClasspath, parsedArgs.targetSdkVersion);
    
                    Thread.currentThread().setContextClassLoader(cl);
                }
    
                /*
                 * Pass the remaining arguments to SystemServer.
                 */
                ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
            }
    
            /* should never reach here */
        }
    
    

    主要实现步骤:

    1、通过设置umask创建文件的默认权限
    2、设置进程名字
    3、获取SYSTEMSERVERCLASSPATH环境变量值(一系列jar),如果需要,则进行dex优化
    5、最后一步,也是最重要的一步:由于invokeWith为null,所以
    会通过RuntimeInit.zygoteInit中调用applicationInit,进而调用invokeStaticMain,然后就会调用SystemServer的main()方法

    至此就算启动完成了,代码还是挺多的 , O(∩_∩)O哈哈~ 需要消化一下.

    参考

    Android系统启动——6 SystemServer启动

    相关文章

      网友评论

        本文标题:Android系统启动之zyogte进程java(下)

        本文链接:https://www.haomeiwen.com/subject/vujrbqtx.html