android systemserver启动详解

文章出处:https://blog.csdn.net/shift_wwx/article/details/45561633

 

前言:之前android zygote之启动过程分析中分析了一下zygote启动的过程,其中涉及的重要部分有三个:一是创建了一个socket,方便了后期AMS与zygote的通讯,为什么一定要zygote通讯其实说白了就是zygote拥有的东西太多,需要分享一下它;二是启动了system_server进程,而这个进程就是用户基本所有service创建和启动的地方,也是android系统启动的关键一步;三是创建了一个loop,处理AMS发到zygote的一些进程处理信息。

 

@/frameworks/vase/core/java/com/android/internal/os/ZygoteInit.java

public class ZygoteInit {
    ......
    
    public static void main(String argv[]) {
        try {
            ......
            
            registerZygoteSocket();
            ......
            
            if (argv[1].equals("start-system-server")) {
                startSystemServer(); 
            } else if (!argv[1].equals("")) {         
                throw new RuntimeException(argv[0] + USAGE_STRING);
            }
            
            ......
            
            runSelectLoop();
            ......
        } catch (MethodAndArgsCaller caller) {
            ......
        }catch (RuntimeException ex) {
            ......
        }
    }
}

来看一下startSystemServer:

/**
 * Prepare the arguments and fork for the system server process.
 */
private static boolean startSystemServer()
        throws MethodAndArgsCaller, RuntimeException {
    long capabilities = posixCapabilitiesAsBits(
        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_RESOURCE,
        OsConstants.CAP_SYS_TIME,
        OsConstants.CAP_SYS_TTY_CONFIG
    );//没看懂,POSIX接口性能?
    /* 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,1032,3001,3002,3003,3006,3007",
        "--capabilities=" + capabilities + "," + capabilities,
        "--runtime-init",
        "--nice-name=system_server",
        "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) {
        handleSystemServerProcess(parsedArgs);
    }

    return true;
}

详细分析:

 

1、args

下面会出现parsedArgs = new ZygoteConnection.Arguments(args);

处理过程是在:

@/frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java

private void parseArgs(String args[])
                throws IllegalArgumentException {
    ......
}

 

1)uid=1000 

@/frameworks/base/core/java/android/os/Process.java

    /**
     * Defines the UID/GID under which system code runs.
     */
    public static final int SYSTEM_UID = 1000;

还有其他特殊的uid定义:

    /**
     * Defines the UID/GID under which the telephony code runs.
     */
    public static final int PHONE_UID = 1001;

    /**
     * Defines the UID/GID for the user shell.
     * @hide
     */
    public static final int SHELL_UID = 2000;

    /**
     * Defines the UID/GID for the log group.
     * @hide
     */
    public static final int LOG_UID = 1007;

    /**
     * Defines the UID/GID for the WIFI supplicant process.
     * @hide
     */
    public static final int WIFI_UID = 1010;

    ......
 

2)gid=1000

3)niceName=system_server这里的niceName就是需要创建的进程名,系统起来ps会看到

4)remainingArgs = new String[args.length - curArg];生下来的应该就是args最后的,这边应该是SystemServer的类名

 

2、forkSystemServer

pid = Zygote.forkSystemServer(
        parsedArgs.uid, parsedArgs.gid,
        parsedArgs.gids,
        parsedArgs.debugFlags,
        null,
        parsedArgs.permittedCapabilities,
        parsedArgs.effectiveCapabilities);

@/libcore/dalvik/src/main/java/dalvik/system/Zygote.java

    public static int forkSystemServer(int uid, int gid, int[] gids, int debugFlags,
            int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
        preFork();
        int pid = nativeForkSystemServer(
                uid, gid, gids, debugFlags, rlimits, permittedCapabilities, effectiveCapabilities);
        postFork();
        return pid;
    }

    native public static int nativeForkSystemServer(int uid, int gid, int[] gids, int debugFlags,
            int[][] rlimits, long permittedCapabilities, long effectiveCapabilities);

@/dalvik/vm/native/dalvik_system_Zygote.cpp

/*
 * native public static int nativeForkSystemServer(int uid, int gid,
 *     int[] gids, int debugFlags, int[][] rlimits,
 *     long permittedCapabilities, long effectiveCapabilities);
 */
static void Dalvik_dalvik_system_Zygote_forkSystemServer(
        const u4* args, JValue* pResult)
{
    pid_t pid;
    pid = forkAndSpecializeCommon(args, true);

    /* The zygote process checks whether the child process has died or not. */
    if (pid > 0) {
        int status;

        ALOGI("System server process %d has been created", pid);
        gDvm.systemServerPid = 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.
         */
        if (waitpid(pid, &status, WNOHANG) == pid) {
            ALOGE("System server process %d has died. Restarting Zygote!", pid);
            kill(getpid(), SIGKILL);
        }
    }
    RETURN_INT(pid);
}

看一下forkAndSpecializeCommon(args, true);其实就是两句话:

    dvmDumpLoaderStats("zygote");
    pid = fork();

system_server就是由zygote fork而来的。

有点不明白,fork出来应该是子进程,pid应该是0,那么这个if是什么时候调用的呢?

应该是作为父进程的时候,会提示,然后对system_server做监控,出问题的时候,会kill掉system_server,然后restart zygote,需要确认一下。

这里有几篇好文章,可以参考一下。

在系统起来之后ps一下看看吧:

root      174   1     627992 19028 ffffffff 400d88f0 S zygote
drm       175   1     12560  4908  ffffffff b6e9c7a4 S /system/bin/drmserver
media     176   1     82836  27872 ffffffff b6e9d7a4 S /system/bin/mediaserver
root      177   1     1004   220   c057e4b8 b6f344e0 S /system/bin/installd
keystore  179   1     3372   1012  c038b40c b6ee77a4 S /system/bin/keystore
root      180   1     1908   492   c00dde38 b6f898f0 S /system/bin/pppoe_wrapper
root      181   1     61328  37876 ffffffff b6efa7a4 S /system/bin/imageserver
media_rw  183   1     3528   440   ffffffff b6f4a4e0 S /system/bin/sdcard
root      185   2     0      0     c0041a1c 00000000 S kworker/3:1H
root      198   2     0      0     c0041a1c 00000000 S kworker/1:1H
root      455   2     0      0     c039b180 00000000 S aml_buf_toggle
system    508   174   732700 40224 ffffffff 400d9954 S system_server
u0_a8     610   174   684360 61076 ffffffff 400d9954 S com.android.systemui

system_server pid是508,ppid是174,而174确实是zygote进程
 

3、handleSystemServerProcess

    /**
     * Finish remaining work for the newly forked system server process.
     */
    private static void handleSystemServerProcess(
            ZygoteConnection.Arguments parsedArgs)
            throws ZygoteInit.MethodAndArgsCaller {

        closeServerSocket();

        // set umask to 0077 so new files and directories will default to owner-only permissions.
        Libcore.os.umask(S_IRWXG | S_IRWXO);

        if (parsedArgs.niceName != null) {
            Process.setArgV0(parsedArgs.niceName);
        }

        if (parsedArgs.invokeWith != null) {
            WrapperInit.execApplication(parsedArgs.invokeWith,
                    parsedArgs.niceName, parsedArgs.targetSdkVersion,
                    null, parsedArgs.remainingArgs);
        } else {
            /*
             * Pass the remaining arguments to SystemServer.
             */
            RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs);
        }

        /* should never reach here */
    }

 由于由Zygote进程创建的子进程会继承Zygote进程中创建的Socket文件描述符,而这里的子进程又不会用到它,因此,这里就调用closeServerSocket函数来关闭它。这个函数接着调用RuntimeInit.zygoteInit函数来进一步执行启动SystemServer组件的操作。

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

        redirectLogStreams();//把system.out和system.err输出重定向到android log中

        commonInit();
        nativeZygoteInit();

        applicationInit(targetSdkVersion, argv);
    }

1)commonInit()

这里很关键哦,很多log中都会看到:

    private static final void commonInit() {
        if (DEBUG) Slog.d(TAG, "Entered RuntimeInit!");

        /* set default handler; this applies to all threads in the VM */
        Thread.setDefaultUncaughtExceptionHandler(new UncaughtHandler());

        /*
         * Install a TimezoneGetter subclass for ZoneInfo.db
         */
        TimezoneGetter.setInstance(new TimezoneGetter() {
            @Override
            public String getId() {
                return SystemProperties.get("persist.sys.timezone");
            }
        });
        TimeZone.setDefault(null);

        /*
         * Sets handler for java.util.logging to use Android log facilities.
         * The odd "new instance-and-then-throw-away" is a mirror of how
         * the "java.util.logging.config.class" system property works. We
         * can't use the system property here since the logger has almost
         * certainly already been initialized.
         */
        LogManager.getLogManager().reset();
        new AndroidConfig();

        /*
         * Sets the default HTTP User-Agent used by HttpURLConnection.
         */
        String userAgent = getDefaultUserAgent();
        System.setProperty("http.agent", userAgent);

        /*
         * Wire socket tagging to traffic stats.
         */
        NetworkManagementSocketTagger.install();

        /*
         * If we're running in an emulator launched with "-trace", put the
         * VM into emulator trace profiling mode so that the user can hit
         * F9/F10 at any time to capture traces.  This has performance
         * consequences, so it's not something you want to do always.
         */
        String trace = SystemProperties.get("ro.kernel.android.tracing");
        if (trace.equals("1")) {
            Slog.i(TAG, "NOTE: emulator trace profiling enabled");
            Debug.enableEmulatorTraceOutput();
        }

        initialized = true;
    }

第一句话加了一个异常捕获的handler:UncaughtHandler

    private static class UncaughtHandler implements Thread.UncaughtExceptionHandler {
        public void uncaughtException(Thread t, Throwable e) {
            try {
                // Don't re-enter -- avoid infinite loops if crash-reporting crashes.
                if (mCrashing) return;
                mCrashing = true;

                if (mApplicationObject == null) {
                    Slog.e(TAG, "*** FATAL EXCEPTION IN SYSTEM PROCESS: " + t.getName(), e);
                } else {
                    StringBuilder message = new StringBuilder();
                    message.append("FATAL EXCEPTION: ").append(t.getName()).append("\n");
                    final String processName = ActivityThread.currentProcessName();
                    if (processName != null) {
                        message.append("Process: ").append(processName).append(", ");
                    }
                    message.append("PID: ").append(Process.myPid());
                    Slog.e(TAG, message.toString(), e);
                }

                // Bring up crash dialog, wait for it to be dismissed
                ActivityManagerNative.getDefault().handleApplicationCrash(
                        mApplicationObject, new ApplicationErrorReport.CrashInfo(e));
            } catch (Throwable t2) {
                try {
                    Slog.e(TAG, "Error reporting crash", t2);
                } catch (Throwable t3) {
                    // Even Slog.e() fails!  Oh well.
                }
            } finally {
                // Try everything to make sure this process goes away.
                Process.killProcess(Process.myPid());
                System.exit(10);
            }
        }
    }

log中经常出现的FATAL EXCEPTION:***就是从这里来的

 

回到commonInit(),其他就是一些初始化,例如时区等

2)nativeZygoteInit

static void com_android_internal_os_RuntimeInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
    gCurRuntime->onZygoteInit();
}

看到这个onZygoteInit很是熟悉,在android zygote之启动过程分析中涉及到:

AppRuntime runtime

调用zygoteInitNative函数来执行一个Binder进程间通信机制的初始化工作,这个工作完成之后,这个进程中的Binder对象就可以方便地进行进程间通信了
3)applicationInit

    private static void applicationInit(int targetSdkVersion, String[] argv)
            throws ZygoteInit.MethodAndArgsCaller {
        // 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);

        // 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;
        }

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

invokeStaticMain:

    private static void invokeStaticMain(String className, String[] argv)
            throws ZygoteInit.MethodAndArgsCaller {
        Class cl;

        try {
            cl = Class.forName(className);
        } 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.
         */
        throw new ZygoteInit.MethodAndArgsCaller(m, argv);
    }

这里会将systemserver的类名传进去,run是在ZygoteInit.main里面。

 

最终就会调用到SystemServer.main(),对于SystemServer后期也会继续分析。请参考android SystemServer详解

 

 

 

 

 

你可能感兴趣的:(android,----,zygote,android,源码分析)