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