开机启动步骤
Android 系统启动流程
第一、启动电源
第二、引导程序:Bootloader
第三、Linux 内核启动
第四、init 进程
第五、Zygote 进程的创建
第六、SystemServer 进程的创建
第七、系统启动完成
稍微详细一点的步骤:
1. android 系统初始化
2. BootLoader 进程 (系统启动之后启动此进程)
3. Linux Kernel (内核启动)
4. init.cpp 进程启动 (用户空间第一个进程), PID(进程号)为“1”
init 进程做了三件重要的事:
① 创建(mkdir)和挂载(mount)启动所需的文件目录。其中挂载了 tmpfs、devpts、proc、sysfs 和 selinuxfs 共 5 种文件系统
② 初始化和启动属性服务(property service)
③ 解析 init.rc 配置文件并启动 Zygote 进程 (读取文件配置信息来启动系统相关的各种服务,比如:AMS、WMS、PMS 等等)
其中还有init.zygote32.rc,init.zygote32_64.rc,init.zygote64.rc,init.zygote64_32.rc 这四个文件
其中init.rc 文件中有一句代码: start zygote
Zygote server执行路径为 system/bin/app_process64,对应的文件为 app_main.cpp,这样就会进入 app_main.cpp 的 main 函数,也就是在 Zygote 的 main 函数中,代码如下:
app_main.cpp
// Parse runtime arguments. Stop at first unrecognized option.
bool zygote = false;
int main(int argc, char* const argv[])
{
...
while (i < argc) {
const char* arg = argv[i++];
if (strcmp(arg, "--zygote") == 0) { // 1
// 如果当前运行在Zygote进程中,则将zygote设置为true
zygote = true;
niceName = ZYGOTE_NICE_NAME;
} else if (strcmp(arg, "--start-system-server") == 0) {
// 如果当前运行在system_server进程中,则将startSystemServer设置为true
startSystemServer = true;
}
...
}
...
// 如果运行在zygote进程中
if (zygote) {
// 启动Zygote
runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
} else if (className) {
runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
} else {
fprintf(stderr, "Error: no class name or --zygote supplied.\n");
app_usage();
LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
return 10;
}
...
}
5. 启动 Zygote(孵化器) 进程 可以提前加载一些资源,这样 fork 出的子进程就可以直接使用这些资源,而不用重新加载。比如:system_server 进程就可以直接使用 Zygote 进程中的 JNI 函数、共享库、常用类以及主题资源。
Zygote 进程启动工作了4件事:
① 调用 AppRuntime.cpp 里的AndroidRuntime.start 方法,创建 Java 虚拟机并为其注册 JNI 方法
AndroidRuntime.cpp
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
...
/* start the virtual machine */
// 创建JAVA虚拟机(JVM)
JniInvocation jni_invocation;
jni_invocation.Init(NULL);
JNIEnv* env;
if (startVm(&mJavaVM, &env, zygote) != 0) {
return;
}
onVmCreated(env);
/*
* Register android functions.
*/
// 注册android 常用的JNI
if (startReg(env) < 0) {
ALOGE("Unable to register all android natives\n");
return;
}
...
/*
* Start VM. This thread becomes the main thread of the VM, and will
* not return until the VM exits.
*/
// 通过反射调用,比如className为:"com.android.internal.os.ZygoteInit"
char* slashClassName = toSlashClassName(className);
jclass startClass = env->FindClass(slashClassName);
if (startClass == NULL) {
ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
/* keep going */
} else {
// className已设定,那么这里就是找到ZygoteInit 里面的main方法
jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
"([Ljava/lang/String;)V");
if (startMeth == NULL) {
ALOGE("JavaVM unable to find main() in '%s'\n", className);
/* keep going */
} else {
// 通过JNI调用ZygoteInit的main方法
env->CallStaticVoidMethod(startClass, startMeth, strArray);
#if 0
if (env->ExceptionCheck())
threadExitUncaughtException(env);
#endif
}
}
free(slashClassName);
...
}
② 通过 JNI 调用 ZygoteInit.main 方法,从 Native 层进入 Java 框架层
③ 启动 system_server 进程;
④ 通过 ZygoteServer 创建服务器端的 Socket,并通过 ZygoteServer.runSelectLoop 方法等待 AMS 的请求来创建新的应用程序进程;
// com.android.internal.os.ZygoteInit.java
public static void main(String argv[]) {
// Mark zygote start. This ensures that thread creation will throw
// an error.
ZygoteHooks.startZygoteNoThreadCreation();
try {
Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "ZygoteInit");
RuntimeInit.enableDdms();
// Start profiling the zygote initialization.
SamplingProfilerIntegration.start();
boolean startSystemServer = false;
String socketName = "zygote";
String abiList = null;
// 读取配置文件传过来的数据,遍历匹配"start-system-server" 则要启动system server
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]);
}
}
if (abiList == null) {
throw new RuntimeException("No ABI list supplied.");
}
// ① 创建一个 Server 端的 Socket 通道
registerZygoteSocket(socketName);
Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "ZygotePreload");
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
SystemClock.uptimeMillis());
//② 预加载类和资源
preload();
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
SystemClock.uptimeMillis());
Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
// Finish profiling the zygote initialization.
SamplingProfilerIntegration.writeZygoteSnapshot();
// Do an initial gc to clean up after startup
Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PostZygoteInitGC");
gcAndFinalize();
Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
// Disable tracing so that forked processes do not inherit stale tracing tags from
// Zygote.
Trace.setTracingEnabled(false);
// Zygote process unmounts root storage spaces.
Zygote.nativeUnmountStorageOnInit();
ZygoteHooks.stopZygoteNoThreadCreation();
if (startSystemServer) {
//③ 启动 system_server 进程,这样系统的服务也会由 system_server 进程启动起来。
startSystemServer(abiList, socketName);
}
Log.i(TAG, "Accepting command socket connections");
//④ 调用 此方法来等待 AMS 创建新进程的请求。
runSelectLoop(abiList);
closeServerSocket();
} catch (MethodAndArgsCaller caller) {
caller.run();
} catch (Throwable ex) {
Log.e(TAG, "Zygote died with exception", ex);
closeServerSocket();
throw ex;
}
}
由以上可知,ZygoteInit.main 方法中主要做了 4 件事情:
① 创建 Server 端的 Socket ,用于响应 ActivityManagerService 创建新的应用进程的请求;
② 预加载类和资源;
③ 启动 system_server 进程,这样系统服务也就会由 system_server 启动起来;
④ 等待 ActivityManagerService 创建新的应用程序进程的请求;
创建一个 Server 端的 Socket 通道,用于响应ActivityManagerService 请求 Zygote 来创建新的应用程序进程的请求。
/**
* Registers a server socket for zygote command connections
* @throws RuntimeException when open fails
*/
private static void registerZygoteSocket(String socketName) {
if (sServerSocket == 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);
sServerSocket = new LocalServerSocket(fd);
} catch (IOException ex) {
throw new RuntimeException(
"Error binding to local socket '" + fileDesc + "'", ex);
}
}
}
启动系统服务:为系统服务器进程准备参数和fork。
/**
* Prepare the arguments and fork for the system server process.
*/
private static boolean startSystemServer(String abiList, String socketName)
throws MethodAndArgsCaller, RuntimeException {
...
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 */
/* For child process 当前运行在 system_server 进程中 */
if (pid == 0) {
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}
handleSystemServerProcess(parsedArgs);
}
return true;
}
system_server 进程复制了 Zygote 进程的地址空间,因此也会得到 Zygote 进程创建的 Socket,这个 Socket 对于 system_server 进程没有任何用处,因此,需要在关闭 Zygote 进程创建的 Socket,
/**
* Finish remaining work for the newly forked system server process.
*/
private static void handleSystemServerProcess(
ZygoteConnection.Arguments parsedArgs)
throws ZygoteInit.MethodAndArgsCaller {
// 关闭 Zygote 进程创建的 Socket
closeServerSocket();
...
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) {
...
} else {
ClassLoader cl = null;
if (systemServerClasspath != null) {
cl = createSystemServerClassLoader(systemServerClasspath,
parsedArgs.targetSdkVersion);
Thread.currentThread().setContextClassLoader(cl);
}
/*
* Pass the remaining arguments to SystemServer.
*/
// 将其余参数传递给SystemServer,以便启动SystemServer用到
RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
}
/* should never reach here */
}
/**
* Creates a PathClassLoader for the system server. It also creates
* a shared namespace associated with the classloader to let it access
* platform-private native libraries.
*/
private static PathClassLoader createSystemServerClassLoader(String systemServerClasspath,
int targetSdkVersion) {
String librarySearchPath = System.getProperty("java.library.path");
return PathClassLoaderFactory.createClassLoader(systemServerClasspath,
librarySearchPath,
null /* libraryPermittedPath */,
ClassLoader.getSystemClassLoader(),
targetSdkVersion,
true /* isNamespaceShared */);
}
在RuntimeInit.java 中的zygoteInit方法里面:nativeZygoteInit() 方法调用的是 Native 层的代码,用来启动 Binder 线程池,这样 ,system_server 进程就可以使用 Binder 与其他进程进行通信。applicationInit()方法是用于进入 system_server 的 main 方法。
// 路径:com.android.internal.os.RuntimeInit.java
/**
* The main function called when started through the zygote process. This
* could be unified with main(), if the native code in nativeFinishInit()
* were rationalized with Zygote startup.<p>
*
* Current recognized args:
* <ul>
* <li> <code> [--] <start class name> <args>
* </ul>
*
* @param targetSdkVersion target SDK version
* @param argv arg strings
*/
public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller {
if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "RuntimeInit");
redirectLogStreams();
commonInit();
// 启动 Binder 线程池
nativeZygoteInit();
// 进入 system_server 的 main 方法
applicationInit(targetSdkVersion, argv, classLoader);
}
1 启动 Binder 线程池
ZygoteInit.nativeZygoteInit() 是一个 Native 方法,首先要了解它对应的 JNI 文件,如下所示:
// 路径:/core/jni/AndroidRuntime.cpp
static void com_android_internal_os_RuntimeInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
gCurRuntime->onZygoteInit();
}
gCurRuntime 是 AndroidRuntime 类型的指针,具体指向的是 AndroidRuntime 的子类 AppRuntime,在 app_main.cpp 中定义。接着来看 AppRuntime.onZygoteInit 方法,代码如下所示:
// 路径:/cmds/app_process/app_main.cpp
virtual void onZygoteInit()
{
sp<ProcessState> proc = ProcessState::self();
ALOGV("App process: starting thread pool.\n");
// 启动一个 Binder 线程池,这样 system_server 进程就可以使用 Binder 与其他进程通信了。因此,从这里可以知道 ZygoteInit.nativeZygoteInit() 函数主要是用来启动 Binder 线程池的。
proc->startThreadPool();
}
2 进入 SystemServer.main 方法
// 路径:com.android.internal.os.RuntimeInit.java
private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller {
...
invokeStaticMain(args.startClass, args.startArgs, classLoader);
}
/**
* Invokes a static "main(argv[]) method on class "className".
* Converts various failing exceptions into RuntimeExceptions, with
* the assumption that they will then cause the VM instance to exit.
*
* @param className Fully-qualified class name
* @param argv Argument vector for main()
* @param classLoader the classLoader to load {@className} with
*/
private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller {
Class<?> cl;
try {
// 通过反射得到 SystemServer 类
cl = Class.forName(className, true, classLoader);
} catch (ClassNotFoundException ex) {
throw new RuntimeException(
"Missing class when invoking static main " + className,
ex);
}
Method m;
try {
// 找到 SystemServer 的 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);
}
/*
* 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.
*/
// 将找到的 main 方法传入到MethodAndArgsCaller构造方法中
throw new ZygoteInit.MethodAndArgsCaller(m, argv);
}
ZygoteInit.main 方法中会在try catch中获取 MethodAndArgsCaller 对象,并调用 MethodAndArgsCaller.run() 方法。MethodAndArgsCaller 是 Zygote 的静态内部类:
// 路径:/core/java/com/android/internal/os/ZygoteInit.java
public static void main(String argv[]) {
...
try {
...
} catch (MethodAndArgsCaller caller) {
caller.run();
} catch (Throwable ex) {
...
throw ex;
}
}
Zygote 中的MethodAndArgsCaller 静态内部类
/**
* Helper exception class which holds a method and arguments and
* can call them. This is used as part of a trampoline to get rid of
* the initial process setup stack frames.
*/
public static class MethodAndArgsCaller extends Exception
implements Runnable {
/** method to call */
private final Method mMethod;
/** argument array */
private final String[] mArgs;
public MethodAndArgsCaller(Method method, String[] args) {
mMethod = method;
mArgs = args;
}
public void run() {
try {
// 此处会被动态调用SystemServer.main 方法。
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);
}
}
}
3 解析 system_server 进程
// 路径:/services/java/com/android/server/SystemServer.java
/**
* The main entry point from zygote.
*/
public static void main(String[] args) {
new SystemServer().run();
}
private void run() {
try {
...
Looper.prepareMainLooper();
Looper.getMainLooper().setSlowLogThresholdMs(
SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS);
// Initialize native services.
// 1 加载了动态库 libandroid_servers.so
System.loadLibrary("android_servers");
...
// Initialize the system context.
// 创建系统的 Context
createSystemContext();
// Create the system service manager.
// 2 创建SystemServiceManager
mSystemServiceManager = new SystemServiceManager(mSystemContext);
mSystemServiceManager.setStartInfo(mRuntimeRestart,
mRuntimeStartElapsedTime, mRuntimeStartUptime);
LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
// Prepare the thread pool for init tasks that can be parallelized
SystemServerInitThreadPool.get();
} finally {
traceEnd(); // InitBeforeStartServices
}
// Start services.
try {
traceBeginAndSlog("StartServices");
// 3 启动引导服务
startBootstrapServices();
// 4 启动核心服务
startCoreServices();
// 5 启动其他服务
startOtherServices();
SystemServerInitThreadPool.shutdown();
} catch (Throwable ex) {
Slog.e("System", "******************************************");
Slog.e("System", "************ Failure starting system services", ex);
throw ex;
} finally {
traceEnd();
}
...
// Loop forever.
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
总结:
① 在注释 1 加载了动态库 libandroid_servers.so。
② 在注释 2 处创建 SystemServiceManager,它会对系统服务进行创建、启动和生命周期管理。
③ 在注释 3 处的 startBootstrapServices() 方法中回用 SystemServiceManager 启动 ActivityManagerService、PowerManagerService、PackageManagerService 等服务。
④ 在注释 4 处的 startCoreServices() 方法中则启动 DropBoxManagerService、BatteryService、UsageStateService 和 WebViewUpdateService。
⑤ 在注释 5 处的 startOtherServices() 方法中启动了 CameraService、AlarmManagerService、VrManagerService 等服务。
⑥ 从注释 3 、4、5 处可以 看出, 官方把系统服务分为三种类型,分别是引导服务、核心服务和其他服务,其中,其他服务是一些非要紧的和不需要立即启动的服务。 系统服务总共 100 多个,以下是其中的部分服务:
6. 在 system_server 进程中会启动 AMS、WMS、PMS 等服务,等这些服务启动之后,AMS 中就会打开 Launcher 应用的 home Activity,最终就看到了手机的 “桌面”。
常见面试题
面试官:你了解 Android 系统启动流程吗?
程序员B:
1、当按电源键触发开机,首先会从 ROM 中预定义的地方加载引导程序 BootLoader 到 RAM 中。
2、并执行 BootLoader 程序启动 Linux Kernel,
3、然后启动用户级别的第一个进程:init 进程。
4、init 进程会解析 init.rc 脚本做一些初始化工作,包括挂载文件系统、创建工作目录以及启动系统服务进程等,其中系统服务进程包括 Zygote、service manager、media 等。
5、在 Zygote 中会进一步去启动 system_server 进程,然后在 system_server 进程中会启动 AMS、WMS、PMS 等服务,
6、等这些服务启动之后,AMS 中就会打开 Launcher 应用的 home Activity,最终就看到了手机的 “桌面”。
面试官:system_server 为什么要在 Zygote 中启动,而不是由 init 直接启动呢?
程序员B:Zygote 作为一个孵化器,可以提前加载一些资源,这样 fork() 时基于 Copy-On-Write 机制创建的其他进程就能直接使用这些资源,而不用重新加载。比如 system_server 就可以直接使用 Zygote 中的 JNI 函数、共享库、常用的类、以及主题资源。
面试官:为什么要专门使用 Zygote 进程去孵化应用进程,而不是让 system_server 去孵化呢?
程序员B:首先 system_server 相比 Zygote 多运行了 AMS、WMS 等服务,这些对一个应用程序来说是不需要的。另外进程的 fork() 对多线程不友好,仅会将发起调用的线程拷贝到子进程,这可能会导致死锁,而 system_server 中肯定是有很多线程的。
面试官:能说说具体是怎么导致死锁的吗?
程序员B:fork() 时只会把调用线程拷贝到子进程、其他线程都会立即停止,那如果一个线程在 fork() 前占用了某个互斥量,fork() 后被立即停止,这个互斥量就得不到释放,再去请求该互斥量就会发生死锁了。
面试官:Zygote 为什么不采用 Binder 机制进行 IPC 通信?
程序员B:Binder 机制的 Binder 线程池是多线程的,如果采用的话就存在上面说的死锁问题了。
其实严格来说,Binder 机制不一定要多线程,所谓的 Binder 线程只不过是在循环读取 Binder 驱动的消息而已,只注册一个 Binder 线程也是可以工作的,比如 service manager 就是这样的。
尽管 Zygote 没有采取 Binder 机制,它也不是单线程的,内部还跑了一些虚拟机相关的守护线程,但它在 fork() 前主动停止了其他线程,fork() 后再重新启动。
参考:
Android系统启动(一)— init 进程启动过程
Android系统启动(二) — Zygote进程启动过程
Android系统启动(三) — SystemServer处理过程
Android系统启动(四) — Launcher 启动过程