Android系统启动过程
首先Android框架架构图:
Linux内核启动之后就到Android Init进程,进而启动Android相关的服务和应用。
启动的过程如下图所示:
Android启动过程
第一步:启动电源以及系统启动
第二步:引导程序
第三步:内核
第四步:init进程
init是第一个进程,我们可以说它是root进程或者说有进程的父进程。init进程有两个责任,一是挂载目录,比如/sys、/dev、/proc,二是运行init.rc脚本。
init是第一个进程,我们可以说它是root进程或者说有进程的父进程。init进程有两个责任,一是挂载目录,比如/sys、/dev、/proc,二是运行init.rc脚本。 第五步:Zygote加载进程
在Java中,我们知道不同的虚拟机实例会为不同的应用分配不同的内存。假如Android应用应该尽可能快地启动,但如果Android系统为每一个应用启动不同的Dalvik虚拟机实例,就会消耗大量的内存以及时间。因此,为了克服这个问题,Android系统创造了”Zygote”。Zygote让Dalvik虚拟机共享代码、低内存占用以及最小的启动时间成为可能。Zygote是一个虚拟器进程,正如我们在前一个步骤所说的在系统引导的时候启动。Zygote预加载以及初始化核心库类。通常,这些核心类一般是只读的,也是Android SDK或者核心框架的一部分。在Java虚拟机中,每一个实例都有它自己的核心库类文件和堆对象的拷贝。
在Java中,我们知道不同的虚拟机实例会为不同的应用分配不同的内存。假如Android应用应该尽可能快地启动,但如果Android系统为每一个应用启动不同的Dalvik虚拟机实例,就会消耗大量的内存以及时间。因此,为了克服这个问题,Android系统创造了”Zygote”。Zygote让Dalvik虚拟机共享代码、低内存占用以及最小的启动时间成为可能。Zygote是一个虚拟器进程,正如我们在前一个步骤所说的在系统引导的时候启动。Zygote预加载以及初始化核心库类。通常,这些核心类一般是只读的,也是Android SDK或者核心框架的一部分。在Java虚拟机中,每一个实例都有它自己的核心库类文件和堆对象的拷贝。 第六步:系统服务或服务
完成了上面几步之后,运行环境请求Zygote运行系统服务。系统服务同时使用native以及java编写,系统服务可以认为是一个进程。同一个系统服务在Android SDK可以以System Services形式获得。系统服务包含了所有的System Services。
完成了上面几步之后,运行环境请求Zygote运行系统服务。系统服务同时使用native以及java编写,系统服务可以认为是一个进程。同一个系统服务在Android SDK可以以System Services形式获得。系统服务包含了所有的System Services。 第七步:引导完成 一旦系统服务在内存中跑起来了,Android就完成了引导过程。在这个时候“ACTION_BOOT_COMPLETED”开机启动广播就会发出去。
Init进程的启动
init进程,它是一个由内核启动的用户级进程。内核自行启动(已经被载入内存,开始运行,
并已初始化所有的设备驱动程序和数据结构等)之后,就通过启动一个用户级程序init的方式,完成引导进程。init始终是第一个进程。
启动过程就是代码init.c中main函数执行过程:system\core\init\init.c
在函数中执行了:文件夹建立,挂载,rc文件解析,属性设置,启动服务,执行动作,socket监听……
下面看两个重要的过程:rc文件解析和服务启动。
rc文件解析
.rc文件是Android使用的初始化脚本文件 (System/Core/Init/readme.txt中有描述:
four broad classes of statements which are Actions, Commands, Services, and Options.)
其中Command 就是系统支持的一系列命令,如:export,hostname,mkdir,mount,等等,其中一部分是 linux 命令,
还有一些是 android 添加的,如:class_start : 启动服务,class_stop :关闭服务,等等。
其中Options是针对 Service 的选项的。
系统初始化要触发的动作和要启动的服务及其各自属性都在rc脚本文件中定义。 具体看一下启动脚本:\system\core\rootdir\init.rc
在解析rc脚本文件时,将相应的类型放入各自的List中.
** 服务启动**
文件解析完成之后将service放入到service_list中。
启动ServiceManager
ServiceManager用来管理系统中所有的binder service,不管是本地的c++实现的还是java语言实现的都需要
这个进程来统一管理,最主要的管理就是,注册添加服务,获取服务。所有的Service使用前都必须先在servicemanager中进行注册。
Zygote进程的启动
Zygote进程是Android和Java世界的开创者。在Android系统中,所有的应用进程和SystemServer进程都是由Zygote进程fork而来。其重要性由此可见一斑。虽然Zygote进程相当于Android系统的根进程,但是事实上它也是由Linux系统的init进程启动的。各个进程的先后顺序为:
init进程 –-> Zygote进程 –> SystemServer进程 –>应用进程
其中Zygote进程由init进程启动,SystemServer进程和应用进程由Zygote进程启动。本文依据6.0源码,主要分析Zygote进程的启动流程。init进程在启动Zygote进程时会调用ZygoteInit#main()。以此为切入点,一步步分析。
源码位置:frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
流程概览
ZygoteInit#main();
public static void main(String argv[]) { try { // 设置DDMS可用 RuntimeInit.enableDdms(); // 初始化启动参数 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; } 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]); } } // 注册socket registerZygoteSocket(socketName); // 预加载各种资源 preload(); ... if (startSystemServer) { // 启动SystemServer进程 startSystemServer(abiList, socketName); } // 监听socket,启动新的应用进程。--后文会讲 runSelectLoop(abiList); closeServerSocket(); } catch (MethodAndArgsCaller caller) { // 通过反射调用SystemServer#main()--后文会讲 caller.run(); } catch (RuntimeException ex) { closeServerSocket(); throw ex; } } 上面是个大概流程,下面会依据源码一步步解释。设置DDMS可用之后初始化各种参数,在此之后注册为Zygote进程注册Socket,预加载各种资源,但这些都不是重点!同学们,重点在于startSystemServer(abiList, socketName)(手敲黑板状)!下面简单贴下registerZygoteSocket(socketName)和preload()源码,不感兴趣的同学可直接略过下面两段代码。 ZygoteInit#registerZygoteSocket() private static void registerZygoteSocket(String socketName) { if (sServerSocket == null) { int fileDesc; final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName; ... FileDescriptor fd = new FileDescriptor(); fd.setInt$(fileDesc); // 不是使用IP和端口、而是使用fd创建socket sServerSocket = new LocalServerSocket(fd); ... } } ZygoteInit#registerZygoteSocket() static void preload() { preloadClasses(); // 加载所需的各种class文件 preloadResources(); // 加载资源文件 preloadOpenGL(); // 初始化OpenGL preloadSharedLibraries(); // 加载系统Libraries preloadTextResources(); //加载文字资源 WebViewFactory.prepareWebViewInZygote(); // 初始化WebView } 启动SystemServer进程 private static boolean startSystemServer(String abiList, String socketName) throws MethodAndArgsCaller, RuntimeException { long capabilities = posixCapabilitiesAsBits( OsConstants.CAP_BLOCK_SUSPEND, OsConstants.CAP_KILL, ... ); /* 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,1032,3001,3002,3003,3006,3007", "--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); // 请求fork SystemServer进程 pid = Zygote.forkSystemServer( parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, parsedArgs.debugFlags, null, parsedArgs.permittedCapabilities, parsedArgs.effectiveCapabilities); } catch (IllegalArgumentException ex) { throw new RuntimeException(ex); } // pid为0表示子进程,即SystemServer进程,从此SystemServer进程与Zygote进程分道扬镳 if (pid == 0) { if (hasSecondZygote(abiList)) { waitForSecondaryZygote(socketName); } handleSystemServerProcess(parsedArgs); } return true; } 前面一大段都在构造参数,直接进到try中的代码块。首先根据args数组构造了一个ZygoteConnection.Arguments,然后根据parsedArgs对象的各种参数调用Zygote#forkSyatemServer()方法fork出第一个子进程,也就是SystemServer进程。最后通过执行handleSystemServerProcess反射调用SystemServer#main()。可以看到,这段代码最主要的作用就是fork出SystemServer进程。这里还看不出反射调用的具体细节,下文会一一分析。 首先看下构造ZygoteConnection.Arguments对象时,具体都做了哪些工作,尤其关注Zygote#forkSystemServer()中几个参数的值。 源码位置:frameworks/base/core/java/com/android/internal/os/ZygoteConnection$Arguments.java Arguments(String args[]) throws IllegalArgumentException { parseArgs(args); } private void parseArgs(String args[]) throws IllegalArgumentException { int curArg = 0; boolean seenRuntimeArgs = false; for ( /* curArg */ ; curArg < args.length; curArg++) { String arg = args[curArg]; if (arg.equals("--")) { curArg++; break; } else if (arg.startsWith("--setuid=")) { if (uidSpecified) { throw new IllegalArgumentException("Duplicate arg specified"); } uidSpecified = true; uid = Integer.parseInt(arg.substring(arg.indexOf('=') + 1)); } else if (arg.startsWith("--setgid=")) { if (gidSpecified) { gidSpecified = true; gid = Integer.parseInt(arg.substring(arg.indexOf('=') + 1)); } else if (arg.startsWith("--target-sdk-version=")) { targetSdkVersionSpecified = true; targetSdkVersion = Integer.parseInt(arg.substring(arg.indexOf('=') + 1)); } ... else if (arg.equals("--runtime-args")) { seenRuntimeArgs = true; } else if (arg.startsWith("--capabilities=")) { capabilitiesSpecified = true; String capString = arg.substring(arg.indexOf('=')+1); String[] capStrings = capString.split(",", 2); if (capStrings.length == 1) { effectiveCapabilities = Long.decode(capStrings[0]); permittedCapabilities = effectiveCapabilities; } else { permittedCapabilities = Long.decode(capStrings[0]); effectiveCapabilities = Long.decode(capStrings[1]); } } else if (arg.startsWith("--setgroups=")) { String[] params = arg.substring(arg.indexOf('=') + 1).split(","); gids = new int[params.length]; for (int i = params.length - 1; i >= 0 ; i–) { gids[i] = Integer.parseInt(params[i]); } } else if (arg.startsWith(“–nice-name=”)) { niceName = arg.substring(arg.indexOf(‘=’) + 1); } else { break; } } // 保存没有被解析的参数 remainingArgs = new String[args.length – curArg]; System.arraycopy(args, curArg, remainingArgs, 0, remainingArgs.length); }
对比传入的args数组,可以发现:parsedArgs.uid=1000、parsedArgs.gid=1000、parsedArgs.gids={“1001”,”1002”,…“3007”}、parsedArgs.gid=1000、parsedArgs.niceName=system_server、parsedArgs.seenRuntimeArgs=true。如果中途结束,保存未解析的参数至remainingArgs数组。 获得Arguments对象之后,就开始请求创建SystemServer进程。
源码位置:frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
ZygoteInit#handleSystemServerProcess()
private static void handleSystemServerProcess( ZygoteConnection.Arguments parsedArgs) throws ZygoteInit.MethodAndArgsCaller { closeServerSocket(); if (parsedArgs.niceName != null) { Process.setArgV0(parsedArgs.niceName); } … // 默认为null if (parsedArgs.invokeWith != null) { … } else { … RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl); } /* should never reach here */ }
由Zygote创建的子进程默认拥有Zygote进程的Socket对象,而子进程又用不上,所以先调用closeServerSocket()关闭它。上一段参数解析时写道:parsedArgs.niceName=system_server,在这里调用Process.setArgV0()设置进程名为:system_server。由于parsedArgs.invokeWith属性默认为null,最后调用RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl)来进一步启动SystemServer,这里的参数parsedArgs.remainingArgs就是上文中保存没有被解析对象的数组。
源码位置:frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
RuntimeInit#zygoteInit()
public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) throws ZygoteInit.MethodAndArgsCaller { // 重定向Log输出 redirectLogStreams(); //初始化运行环境 commonInit(); //启动Binder线程池 nativeZygoteInit(); //调用程序入口函数 applicationInit(targetSdkVersion, argv, classLoader); }
RuntimeInit#applicationInit()
private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) throws ZygoteInit.MethodAndArgsCaller { // 初始化虚拟机环境 VMRuntime.getRuntime().setTargetHeapUtilization(0.75f); VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion); final Arguments args; try { args = new Arguments(argv); } catch (IllegalArgumentException ex) { return; } // Remaining arguments are passed to the start class’s static main invokeStaticMain(args.startClass, args.startArgs, classLoader); }
RuntimeInit#invokeStaticMain()
private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader) throws ZygoteInit.MethodAndArgsCaller { Class> cl; try { cl = Class.forName(className, true, classLoader); } catch (ClassNotFoundException ex) { throw new RuntimeException(“Missing class when invoking static main ” + className, ex); } Method m; try { // 获取main方法 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); } throw new ZygoteInit.MethodAndArgsCaller(m, argv); }
这里传入的className就是com.android.server.SystemServer,然后获取main方法,接着判断修饰符,必须是static而且必须是public类型。最有意思的莫过于做完这一切之后,抛出了个MethodAndArgsCaller异常。辛苦辛苦各种初始化,各种变着法儿的调用,最后你居然给我抛个异常!!先别急,这个异常在Zygote#main()方法中捕获。这么做的作用是清除应用程序进程创建过程的调用栈。
public static void main(String argv[]) { try { … startSystemServer(abiList, socketName); … } catch (MethodAndArgsCaller caller) { caller.run(); } }
跟进MethodAndArgsCaller#run(),感觉要出大事情!!
public void run() { try { mMethod.invoke(null, new Object[] { mArgs }); } catch (IllegalAccessException ex) { throw new RuntimeException(ex); } catch (InvocationTargetException ex) { Throwable cause = ex.getCause(); if (cause instanceof RuntimeException) { throw (RuntimeException) cause; } else if (cause instanceof Error) { throw (Error) cause; } throw new RuntimeException(ex); } }
可以看到在这里通过反射调用了com.android.server.SystemServer#main(String[] args)。至此,Zygote进程fork出SystemServer进程,并成功调用SystemServer#main()。
现在SystemServer进程也创建了,main方法也调用了。Zygote进程的使命就此完结了吗?上文我们说道:所有的应用进程和SystemServer进程都是由Zygote进程fork而来。现在有关SystemServer进程的已经告一段落,那有关应用进程呢?
让我们再次回到ZygoteInit#main()
public static void main(String argv[]) { … startSystemServer(abiList, socketName); runSelectLoop(abiList); closeServerSocket(); }
main方法中前面所有的代码好像都和应用进程没有关系,最后一行又是关闭socket,看来和应用进程相关的设置都在runSelectLoop()中,跟进。
监听Socket,启动应用进程
ZygoteInit#runSelectLoop()、ZygoteInit#acceptCommandPeer()
private static void runSelectLoop(String abiList) throws MethodAndArgsCaller { ArrayList