Android系统启动过程详解
来源:互联网 发布:python 字符串变数字 编辑:程序博客网 时间:2024/04/30 12:00
前言
一直想研究Android完整的启动过程,网上看了不少资料,也看了书上的一些说明,对这些观点有些怀疑,于是自己分析了系统启动的完整过程。从内核启动第一个用户程序init开始说起,直到Home应用的启动,每一步都有源代码展示。希望能解除读者对Android系统启动过程中的困惑,若有什么疑问,欢迎留言交流。本研究基于CM10.1源码,读者若能对照源代码查看效果会更好。
1) init启动servicemanager和 zygote两个service
Android底层是Linux内核,和linux类似,内核初始化后启动的第一个用户进程是init,它会解析init.rc脚本,启动init.rc里声明的service,并执行一些action。在init.rc里有启动Andriod空间的一些关键服务,代码如下:
#…service servicemanager /system/bin/servicemanager class core user system group system critical onrestart restart zygote onrestart restart media onrestart restart surfaceflinger onrestart restart drmservice zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server class main socket zygote stream 660 root system onrestart write /sys/android_power/request_state wake onrestart write /sys/power/state on onrestart restart media onrestart restart netd#…
servicemanager负责管理所有的binder service, 这些binder service有native的,也有java的。native的binder service有surfaceflinger,drm,media等,java的binder service就有我们平常熟悉的很多管理服务了,ActivityManagerService,WindowManagerService,BatteryService,PowerManagerService,InputManagerService等等。service manager并不负责这些binder service的创建,native的binder service大多由init启动init.rc里的service时创建并启动,java层的binder service大多由zygote创建并启动的,接下来会详细这些service是如何被启动的。
2) zygote service启动java层的ZygoteInit
zygote服务是java层所有程序进程的父进程,它是Android空间程序的孵化器,Android空间所有程序都是由zygote进程启动的。zygote service对应/system/bin/app_process程序,源代码位于frameworks/base/cmds/app_process/app_main.cpp,启动时的main函数代码如下:
int main(int argc, const char* const argv[]){//.../*runtime就是dalvik虚拟机实例,启动Java层应用时, *会fork 一个子进程,复制虚拟机,许多书上将runtime看作一个进程, *然后再启动zygote进程,个人觉得这是错误的 */ AppRuntime runtime;//... while (i < argc) { const char* arg = argv[i++]; if (!parentDir) { parentDir = arg; /*init.rc启动app_main会设置参数--zygote*/ } else if (strcmp(arg, "--zygote") == 0) { zygote = true; niceName = "zygote"; //进程的名字 /*init.rc启动app_main会设置参数--start-system-server, *表示需启动systemserver */ } else if (strcmp(arg, "--start-system-server") == 0) { startSystemServer = true; /*启动应用时会使用--application参数*/ } else if (strcmp(arg, "--application") == 0) { application = true;/*--nice-name=参数表示要设置的进程名字*/ } else if (strncmp(arg, "--nice-name=", 12) == 0) { niceName = arg + 12; } else { className = arg; break; }} /*设置进程名*/if (niceName && *niceName) { setArgv0(argv0, niceName); set_process_name(niceName);}/*设置虚拟机运行环境的父目录*/runtime.mParentDir = parentDir;if (zygote) {/*虚拟机里启动com.android.internal.os.ZygoteInit, *并传递参数start-system-server */ runtime.start("com.android.internal.os.ZygoteInit", startSystemServer ? "start-system-server" : "");} else if (className) { /*若不是zygote,则启动的第一个类是com.android.internal.os.RuntimeInit, *RumtimeInit初始化后会启动mClassName */ runtime.mClassName = className; runtime.mArgC = argc - i; runtime.mArgV = argv + i; runtime.start("com.android.internal.os.RuntimeInit", application ? "application" : "tool");} 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;}//...}
通过上述代码可知道zygote service将运行dalvik虚拟机,并在虚拟机里执行com.android.internal.os.ZygoteInit,还给它传递了参数start-system-server
3) ZygoteInit启动SystemServer
ZygoteInit启动时的相关源代码:
public static void main(String argv[]) {{try { //... //在某个描述符上监听连接请求, //其它Android空间的程序的启动都是通过连接zygote才孵化出来的 registerZygoteSocket(); //... if (argv[1].equals("start-system-server")) { //启动SystemServer startSystemServer(); } else if (!argv[1].equals("")) { throw new RuntimeException(argv[0] + USAGE_STRING); } //... /*ZYGOTE_FORK_MODE默认为false,如果为true的话,每收到一个连接请求, *就会建立一个新进程,然后再运行连接请求所要求执行的命令,此时会建立另一个新进程 */ if (ZYGOTE_FORK_MODE) { runForkMode(); } else { //使用Select poll的方式来建立新进程,收到连接请求后,也会建立进程启动某个程序 runSelectLoopMode(); } closeServerSocket();} catch (MethodAndArgsCaller caller) { caller.run();} catch (RuntimeException ex) { Log.e(TAG, "Zygote died with exception", ex); closeServerSocket(); throw ex;}}从上述代码可知道会调用startSystemServer以启动SystemServer,相关源代码如下:
private static boolean startSystemServer(){/* Hardcoded command line to start the system server *///启动SystemServer使用的参数String args[] = { "--setuid=1000", "--setgid=1000", "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,3001,3002,3003,3004,3006,3007,3009", "--capabilities=130104352,130104352", "--runtime-init", "--nice-name=system_server", //注意:就是在这里设置要启动的SystemServer包名及类名,故此后续才能启动SystemServer "com.android.server.SystemServer",};ZygoteConnection.Arguments parsedArgs = null;int pid;try { /*将args参数传给ZygoteConnection进行转化,--形式的参数将全部被接收 * 但是要启动的类的类名com.android.server.SystemServer会放在 *ZygoteConnection.Arguments的remainingArgs里,后来调用handleSystemServerProcess时会用到 */ parsedArgs = new ZygoteConnection.Arguments(args); /*添加额外运行参数*/ ZygoteConnection.applyDebuggerSystemProperty(parsedArgs); ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs); /*开启新进程*/ 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会执行ZygoteConnection.Arguments的remainingArgs参数 *所指定的类,即com.android.server.SystemServer */ handleSystemServerProcess(parsedArgs);}}
ZygoteInit的startSystemServer会调用forkSystemServer,然后:
ZygoteInit.forkSystemServer -> Zygote.nativeForkSystemServer-> dalvik_system_Zygote.cpp 里的Dalvik_dalvik_system_Zygote_forkSystemServer-> forkAndSpecializeCommon->fork建立新进程
ZygoteInit的startSystemServer会调用handleSystemServerProcess来真正启动systemserver,相关源代码如下:
然后的流程是
RuntimeInit.zygoteInit-> applicationInit,applicationInit的代码如下所示:
4) SystemServer 启动过程
执行com.android.server.SystemServer时,main函数里会调用init1函数,init1函数是一个本地函数,init1的实现放在frameworks/base/services/jni/com_android_server_SystemServer.cpp里,对应的jni函数是android_server_SystemServer_init1,在该函数里会调用system_init,而system_init的实现是在frameworks/base/cmds/system_server/library/system_init.cpp,该函数的实现代码如下所示:
5) 启动Java层的各种binder service
调用SystemServer的init2函数后,会开启新线程android.server.ServerThread,在新线程里会启动各种Java层的binder service,并在service manager里注册,这些Service大多开启了新线程运行,故此都是systemserver的子线程,添加的Service列表如下所示:
上述并没有看到将ActivityManagerService添加到servicemanager管理,它的添加过程比较特别。在线程android.server.ServerThread里会调用ActivityManagerService.setSystemProcess();setSystemProcess函数的代码如下所示:
可以看到ActivityManagerService采用了单例模式,并调用ServiceManager.addService(“activity”, m, true);将ActivityManagerService交给servicemanager管理,在ActivityManagerService里还添加了别的binder service,像MemBinder,GraphicsBinder,DbBinder。
最后会调用Looper.loop();进入loop循环,等待和别的程序通信。
6) 启动系统界面
线程android.server.ServerThread里有如下代码:
startSystemUi就是用于启动系统界面的,代码如下:
这样便启动了com.android.systemui应用,该应用将启动PowerUI和RingtonePlayer两个线程。
7) 启动Home 程序
线程android.server.ServerThread里有如下代码:
ActivityManagerService.self().systemReady有如下代码:
ActivityStack. resumeTopActivityLocked()有如下代码:
resumeTopActivityLocked的实现有如下代码:
mService类型是ActivityManagerService,ActivityManagerService. startHomeActivityLocked的实现有如下代码:
这样先找到使用Intent.CATEGORY_HOME声明的Activity组件,然后再调用mMainStack.startActivityLocked启动该Activity。
system server启动Home程序总结:
android.server.ServerThread->ActivityManagerService.self().systemReady->mMainStack.resumeTopActivityLocked->resumeTopActivityLocked-> mService.startHomeActivityLocked-> intent.addCategory(Intent.CATEGORY_HOME);mMainStack.startActivityLocked
总结
内核初始化好后,运行的第一个用户程序是init,init将启动init.rc里声明的多个service,跟Android空间相关的有servicemanager和zygote,servicemanager负责管理所有的binder service,zygote负责孵化所有Android空间的程序。zygote service对应的程序是app_process,不过加了一些启动参数,所以它会启动Java层的ZygoteInit,在ZygoteInit里会启动SystemServer,SystemServer分为两个阶段:本地的init1和Java层的init2,init2里会启动线程android.server.ServerThread。在android.server.ServerThread线程里会启动Java层的各种binder service,比如ActivityManagerService,PackageManagerService,WindowManagerService。然后调用ActivityManagerService的systemReady方法,在该方法里会启动系统界面以及Home程序。
- Android系统启动过程详解
- Android系统启动过程详解
- Android系统启动过程详解
- Android系统启动过程详解
- Android系统启动过程详解
- Android系统启动过程详解
- Android系统启动过程详解
- Android 系统启动过程详解
- linux内核启动+Android系统启动过程详解
- linux内核启动+Android系统启动过程详解
- Linux系统启动过程详解
- Linux系统启动过程详解
- Ubuntu系统启动过程详解
- Ubuntu系统启动过程详解
- Linux系统启动过程详解
- Ubuntu系统启动过程详解
- Linux 系统启动过程详解
- 系统启动过程详解
- axure7.0 动态面板 一个按钮 跳转到不同页的动态面板某个状态
- UIApplicationMain笔记
- LeetCode | Construct Binary Tree from Preorder and Inorder Traversal
- 判断js中的类型:typeof / instanceof / constructor / prototype
- mvc使用Newtonsoft.Json反序列化json数据
- Android系统启动过程详解
- 判断是否是直角三角形的算法研究
- 常见的共面阻抗计算模型
- iOS中arc的设置与使用
- Exynos4412裸机开发系列教程--LED流水灯
- 走得太快,别忘了为什么出发——涨粉如此艰难的今天,我如何用7个月做到10万粉丝?
- 关于cocos2d-x2.2.3中定时器<update>的详细解释和使用
- ContentResolver
- LeetCode | Construct Binary Tree from Inorder and Postorder Traversal