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() {@Overridepublic 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 dismissedActivityManagerNative.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 exitreturn;}// Remaining arguments are passed to the start class's static maininvokeStaticMain(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详解

 

 

 

 

 


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部