c_strings.push_back(nullptr);
if (sigstop) {
kill(getpid(), SIGSTOP);
}
// 2. c_strings[0]是执行程序路径,即如果启动的是zygote服务时,execve会运行/system/bin/app_process64
return execv(c_strings[0], c_strings.data()) == 0;
}
2.1 native层app_process
首先运行可执行程序app_process的入口main函数:
/frameworks/base/cmds/app_process/app_main.cpp/
int main(int argc, char* const argv[])
{
…
// Parse runtime arguments. Stop at first unrecognized option.
bool zygote = false;
…
while (i < argc) {
const char* arg = argv[i++];
if (strcmp(arg, “–zygote”) == 0) {
zygote = true; // 参数标识启动zygote进程
niceName = ZYGOTE_NICE_NAME;
} else if (strcmp(arg, “–start-system-server”) == 0) {
startSystemServer = true; //参数标识启动system_server进程
}
…
}
…
if (!niceName.isEmpty()) {
runtime.setArgv0(niceName.string(), true /* setProcName */); // 进程名app_process修改为zygote
}
if (zygote) {
// 启动Zygote,执行AndroidRuntime.start函数
runtime.start(“com.android.internal.os.ZygoteInit”, args, zygote);
} else if (className) {
runtime.start(“com.android.internal.os.RuntimeInit”, args, zygote);
} else {
…
}
}
我们进一步来看AndroidRuntime的start流程代码:
/frameworks/base/core/jni/AndroidRuntime.cpp/
void AndroidRuntime::start(const char* className, const Vector& options, bool zygote)
{
ALOGD(“>>>>>> START %s uid %d <<<<<<\n”,
className != NULL ? className : “(unknown)”, getuid());
…
/* start the virtual machine /
JniInvocation jni_invocation;
jni_invocation.Init(NULL);
JNIEnv env;
if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) {// 1.启动VM虚拟机
return;
}
onVmCreated(env);
/*
- Register android functions.
/
if (startReg(env) < 0) { // 2.注册框架JNI调用到虚拟机中
ALOGE(“Unable to register all android natives\n”);
return;
}
…
char slashClassName = toSlashClassName(className != NULL ? className : “”);
jclass startClass = env->FindClass(slashClassName);
if (startClass == NULL) {
ALOGE(“JavaVM unable to locate class ‘%s’\n”, slashClassName);
} else {
// 3.JNI调用进入java层执行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 {
env->CallStaticVoidMethod(startClass, startMeth, strArray);
…
}
…
}
从代码中可以看到AndroidRuntime#start方法中主要完成三件事情:
-
启动进程的VM虚拟机;
-
注册Android系统框架JNI调用到虚拟机中;
-
通过JNI调用进入java层执行ZygoteInit的main函数;
2.2 java层ZyogeInit
我们继续往下看简化的代码流程:
/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java/
public static void main(String[] argv) {
ZygoteServer zygoteServer = null;
…
try {
…
for (int i = 1; i < argv.length; i++) {
if (“start-system-server”.equals(argv[i])) {
// 在init.rc文件中,有–start-system-server参数,表示要创建SystemServer
startSystemServer = true;
} else if (“–enable-lazy-preload”.equals(argv[i])) {
enableLazyPreload = true;
}
…
}
…
// In some configurations, we avoid preloading resources and classes eagerly.
// In such cases, we will preload things prior to our first fork.
if (!enableLazyPreload) {
…
preload(bootTimingsTraceLog);// 1.预加载资源
…
}
…
zygoteServer = new ZygoteServer(isPrimaryZygote); // 2.创建Socket服务端
if (startSystemServer) {
// 3.fork启动system_server进程
Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
…
}
//4. sokcet服务端等待AMS请求(AMS会通过socket请求Zygote来创建应用程序进程)
caller = zygoteServer.runSelectLoop(abiList);
} catch (Throwable ex) {
Log.e(TAG, “System zygote died with exception”, ex);
throw ex;
}
…
}
static void preload(TimingsTraceLog bootTimingsTraceLog) {
…
preloadClasses();// 1.加载system/etc/preloaded-classes文件中定义的各个系统类
…
preloadResources(); // 2.加载系统中定义的各个drawables、color资源
…
}
从代码中可以看到ZygoteInit#main方法中主要fork启动system_server进程:
-
zygote进程中预加载类、主题资源、字体资源等,基于linux的copy-on-write机制,从而加速后续zygote fork创建出的应用进程的启动速度;
-
创建socket服务端,用于跨进程通信;
-
fork创建启动系统system_server进程;
-
Sokcet服务端进入循环监听等待,等待后续AMS请求(AMS会通过socket请求Zygote来创建应用程序进程)。
3. system_server进程的启动
我们接着ZygoteInit#forkSystemServer往下看:
/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java/
private static Runnable forkSystemServer(String abiList, String socketName,
ZygoteServer zygoteServer) {
…
/* Hardcoded command line to start the system server */
// 1.构建启动system_server进程的相关设置参数
String[] args = {
“–setuid=1000”,
“–setgid=1000”,
“–setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,”
- “1024,1032,1065,3001,3002,3003,3006,3007,3009,3010,3011”,
“–capabilities=” + capabilities + “,” + capabilities,
“–nice-name=system_server”,
“–runtime-args”,
“–target-sdk-version=” + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
// system_server启动的类名
“com.android.server.SystemServer”,
};
…
try {
…
/* Request to fork the system server process */
// 2.fork创建system_server进程,具体实现在native层
pid = Zygote.forkSystemServer(
parsedArgs.mUid, parsedArgs.mGid,
parsedArgs.mGids,
parsedArgs.mRuntimeFlags,
null,
parsedArgs.mPermittedCapabilities,
parsedArgs.mEffectiveCapabilities);
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}
/* For child process */
if (pid == 0) {
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}
zygoteServer.closeServerSocket();
// 3.pid为0代表在新创建的system_server进程中,继续通过handleSystemServerProcess进一步处理
return handleSystemServerProcess(parsedArgs);
}
return null;
}
/**
- Finish remaining work for the newly forked system server process.
/
private static Runnable handleSystemServerProcess(ZygoteArguments parsedArgs) {
…
if (parsedArgs.mInvokeWith != null) {
…
} else {
…
/ - Pass the remaining arguments to SystemServer.
*/
// 调用ZygoteInit#zygoteInit函数具体处理
return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
parsedArgs.mDisabledCompatChanges,
parsedArgs.mRemainingArgs, cl);
}
}
public static Runnable zygoteInit(int targetSdkVersion, long[] disabledCompatChanges,
String[] argv, ClassLoader classLoader) {
…
// 1.RuntimeInit初始化,通过setDefaultUncaughtExceptionHandler设置默认的异常处理机制
RuntimeInit.commonInit();
// 2.触发启动进程的Binder线程池
ZygoteInit.nativeZygoteInit();
// 3.内部经过层层调用,最终通过反射创建"com.android.server.SystemServer"类对象并执行其main函数
return RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv,
classLoader);
}
继续结合代码看看RuntimeInit#applicationInit是如何实现反射创建"com.android.server.SystemServer"类对象并执行其main函数的:
/frameworks/base/core/java/com/android/internal/os/RuntimeInit.java/
protected static Runnable applicationInit(int targetSdkVersion, long[] disabledCompatChanges,
String[] argv, ClassLoader classLoader) {
…
return findStaticMain(args.startClass, args.startArgs, classLoader);
}
protected static Runnable findStaticMain(String className, String[] argv,
ClassLoader classLoader) {
Class<?> cl;
try {
// 1.通过反射加载构建"com.android.server.SystemServer"类对象
cl = Class.forName(className, true, classLoader);
} catch (ClassNotFoundException ex) {
throw new RuntimeException(
"Missing class when invoking static main " + className,
ex);
}
Method m;
try {
//2.访问获取"com.android.server.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);
}
…
/*
- 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.
*/
// 3.通过抛异常触发执行main函数并清除调用栈
return new MethodAndArgsCaller(m, argv);
}
static class MethodAndArgsCaller 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 {
// 通过反射调用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);
}
}
}
从上面的分析中可以看到,system_server进程创建后,会通过反射创建"com.android.server.SystemServer"入口类对象并执行其main方法,我们继续往下看代码简化流程:
/frameworks/base/services/java/com/android/server/SystemServer.java/
public static void main(String[] args) {
new SystemServer().run();
}
private void run() {
…
// 1.创建主线程Looper
Looper.prepareMainLooper();
// 2.创建系统Context上下文
createSystemContext();
// 3.创建SystemServiceManager,用于后续系统服务(AMS、WMS等)的创建、启动和生命周期管理
mSystemServiceManager = new SystemServiceManager(mSystemContext);
mSystemServiceManager.setStartInfo(mRuntimeRestart, mRuntimeStartElapsedTime, mRuntimeStartUptime);
LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
// 4.服务根据优先级被分成3批来启动:
try {
t.traceBegin(“StartServices”);
//启动引导服务,如AMS、PMS等
startBootstrapServices(t);
//启动核心服务
startCoreServices(t);
//启动其他服务
startOtherServices(t);
} catch (Throwable ex) {
Slog.e(“System”, “******************************");
Slog.e(“System”, " Failure starting system services”, ex);
throw ex;
} finally {
t.traceEnd(); // StartServices
}
// 5.开启looper循环
Looper.loop();
}
总结一下上述流程,system_server进程创建之后,主要做了如下几件事情:
-
启动进程的Binder线程池;
-
创建SystemServiceManager大管家,用于后续系统服务(AMS、WMS等)的创建、启动和生命周期管理;
-
用SystemServiceManager按照优先级启动系统各个服务;
-
创建并启动进程的主线程的loop循环;
4. Launcher应用的启动
我们接上一节system_server进程创建之后启动系统服务的流程往下看,以AMS服务的启动为例,相关简化代码流程如下:
/frameworks/base/services/java/com/android/server/SystemServer.java/
private void startBootstrapServices(@NonNull TimingsTraceAndSlog t) {
…
t.traceBegin(“StartActivityManager”);
// 1.SystemServiceManager启动AMS服务
ActivityTaskManagerService atm = mSystemServiceManager.startService(
ActivityTaskManagerService.Lifecycle.class).getService();
mActivityManagerService = ActivityManagerService.Lifecycle.startService(
mSystemServiceManager, atm);
mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
mActivityManagerService.setInstaller(installer);
mWindowManagerGlobalLock = atm.getGlobalLock();
t.traceEnd();
…
}
private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
…
// We now tell the activity manager it is okay to run third party
// code. It will call back into us once it has gotten to the state
// where third party code can really run (but before it has actually
// started launching the initial applications), for us to complete our
// initialization.
// 2.从这里开始便可以开始启动三方APP应用(如Launcher)
mActivityManagerService.systemReady(() -> {
…
}, t);
}
从上面的代码流程中可以看到system_server进程创建之后,启动系统各核心服务的最后会调用到mActivityManagerService#systemReady便可正式开始启动三方APP应用(如Launcher),我们继续往下看:
/frameworks/base/services/java/com/android/server/am/ActivitymanagerService.java/
public void systemReady(final Runnable goingCallback, TimingsTraceAndSlog t){
…
if (bootingSystemUser) {
t.traceBegin(“startHomeOnAllDisplays”);
// 由于Android系统支持多用户和多显示,调用startHomeOnAllDisplays启动每个display上的Home Activity
mAtmInternal.startHomeOnAllDisplays(currentUserId,“systemReady”);
t.traceEnd();
}
}
startHomeOnAllDisplays中经过层层调用最终会调用到startHomeActivity启动Category类型为CATEGORY_HOME类型的应用,也就是Launcher桌面,相关代码简化流程如下:
/frameworks/base/services/java/com/android/server/wm/RootWindowContainer.java/
boolean startHomeOnTaskDisplayArea(int userId, String reason, TaskDisplayArea taskDisplayArea,
boolean allowinstrumenting, boolean fromHomeKey){
…
// 最终调用startHomeActivity启动Category类型为CATEGORY_HOME类型的应用,也就是Launcher桌面
mService.startActivityStartController().startHomeActivity(homeIntent, aInfo, myReason, taskDisplayArea);
return true;
}
5.调试建议
假如你的手机遇到开机比较慢的问题,我们该如何去定位问题的原因出在哪儿呢?这里提供几点调试建议:
5.1 基于系统log定位问题
重启手机,在开机时使用如下adb命令抓取相关日志:
adb shell “logcat -b events |grep “boot_p””
06-03 09:43:19.554 730 730 I boot_progress_start: 4274 //标志着系统kernel启动完成,第一个用户空间进程init进程启动,耗时4274ms
06-03 09:43:19.768 730 730 I boot_progress_preload_start: 4487 //标志着zygote进程开始preload预加载资源
06-03 09:43:20.669 730 730 I boot_progress_preload_end: 5389 //标志着zygote进程preload预加载资源完成
06-03 09:43:21.082 1196 1196 I boot_progress_system_run: 5802 // 标志着system_server进程启动
06-03 09:43:22.186 1196 1196 I boot_progress_pms_start: 6905 // 标志着系统pkms服务启动并开始扫描已安装应用的动作
06-03 09:43:22.430 1196 1196 I boot_progress_pms_system_scan_start: 7150
06-03 09:43:22.757 1196 1196 I boot_progress_pms_data_scan_start: 7477
06-03 09:43:23.033 1196 1196 I boot_progress_pms_scan_end: 7753
06-03 09:43:23.185 1196 1196 I boot_progress_pms_ready: 7905// // 标志着系统pkms服务扫描完成
06-03 09:43:24.133 1196 1196 I boot_progress_ams_ready: 8853 // 标志着AMS已经进入systemReady状态可以启动Home Activity
06-03 09:43:25.468 1196 1523 I boot_progress_enable_screen: 10187 // 标志着锁频界面已经点亮显示,整个开机完成,耗时10187ms
5.2 使用bootchart性能分析工具定位问题
bootchart是一个用于linux启动过程性能分析的开源工具软件,在系统启动过程中自动收集CPU占用率、磁盘吞吐率、进程等信息,并以图形方式显示分析结果,可用作指导优化系统启动过程。Android 系统源码中有bootchart的实现,路径在system/core/init/bootchart.cpp。具体使用方法可以参考下文进行操作: blog.csdn.net/qq_19923217…
6. 总结
最后还是用一张图总结Android系统的启动核心流程:
![Android系统开机启动流程.png](https://i-blog.csdnimg.cn/blog_migrate/4ac0349779f7023b624e11ceed91f6bd.png)
7. 参考文章
图解 | Android系统的启动 juejin.cn/post/688478…
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)
![](https://i-blog.csdnimg.cn/blog_migrate/ea5643ad1edbcea54c085418b1a56e5d.jpeg)
如何做好面试突击,规划学习方向?
面试题集可以帮助你查漏补缺,有方向有针对性的学习,为之后进大厂做准备。但是如果你仅仅是看一遍,而不去学习和深究。那么这份面试题对你的帮助会很有限。最终还是要靠资深技术水平说话。
网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。建议先制定学习计划,根据学习计划把知识点关联起来,形成一个系统化的知识体系。
学习方向很容易规划,但是如果只通过碎片化的学习,对自己的提升是很慢的。
我们搜集整理过这几年字节跳动,以及腾讯,阿里,华为,小米等公司的面试题,把面试的要求和技术点梳理成一份大而全的“ Android架构师”面试 Xmind(实际上比预期多花了不少精力),包含知识脉络 + 分支细节。
我们在搭建这些技术框架的时候,还整理了系统的高级进阶教程,会比自己碎片化学习效果强太多
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
果你仅仅是看一遍,而不去学习和深究。那么这份面试题对你的帮助会很有限。最终还是要靠资深技术水平说话。
网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。建议先制定学习计划,根据学习计划把知识点关联起来,形成一个系统化的知识体系。
学习方向很容易规划,但是如果只通过碎片化的学习,对自己的提升是很慢的。
我们搜集整理过这几年字节跳动,以及腾讯,阿里,华为,小米等公司的面试题,把面试的要求和技术点梳理成一份大而全的“ Android架构师”面试 Xmind(实际上比预期多花了不少精力),包含知识脉络 + 分支细节。
[外链图片转存中…(img-ljEWT8By-1713274891789)]
我们在搭建这些技术框架的时候,还整理了系统的高级进阶教程,会比自己碎片化学习效果强太多
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!