目录
前言
默认情况下,每一个Android应用程序,都是一个独立的进程,并且每个进程都运行在一个独立的虚拟机中,这点我想很多人应该都知道。那么大家有没有想过,每一个应用进程和虚拟机,都是由谁创建的呢?创建的时机又是怎么样的呢?如何尽量减少创建一个新的进程的性能损耗呢?(即如何缩短应用的启动时间)
Zygote简介
我们今天要说的主角,就是Zygote,这个单词的中文翻译叫做“受精卵”,顾名思义,这就是Android应用程序的起点,它是 Android 系统中的第一个 Java 进程
Zygote的作用
- 加载常用类、JNI函数、主题资源、共享库
- 启动虚拟机
- 初始化binder机制
- 启动
SystemServer
(稍后具体分析) - 孵化应用进程
Zygote从何而来
那么这个Zygote又是由谁创建的呢?
Android系统启动后,首先引导加载程序会加载内核并启动init进程。然后,init进程会去读取一个配置文件init.rc,这个配置文件记录了需要启动的系统服务,例如android调试守护进程,USB守护进程等。当然这其中也包含创建Zygote进程的配置
有兴趣的可以通过adb shell查看设备中的文件,这里推荐使用模拟器(可以通过su
命令获取root权限)
下面粘贴了部分文件的内容
/vendor/default.prop
ro.zygote=zygote64_32
/init.rc
import /init.${ro.zygote}.rc
on zygote-start && property:ro.crypto.state=...
# A/B update verifier that marks a successful boot.
exec_start update_verifier_nonencrypted
start netd
start zygote
start zygote_secondary
/init.zygote64_32.rc
这里可以看出启动Zygote真正执行的其实是/system/bin/目录下的app_process64程序
#zygote代表进程名称
#/system/bin/app_process64代表程序的可执行路径
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
class main
priority -20
user root
group root readproc reserved_disk
socket zygote stream 660 root system
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart audioserver
onrestart restart cameraserver
onrestart restart media
onrestart restart netd
onrestart restart wificond
writepid /dev/cpuset/foreground/tasks
service zygote_secondary /system/bin/app_process32 -Xzygote /system/bin --zygote --socket-name=zygote_secondary --enable-lazy-preload
class main
priority -20
user root
group root readproc reserved_disk
socket zygote_secondary stream 660 root system
onrestart restart zygote
writepid /dev/cpuset/foreground/tasks
所以总结一句话,Zygote就是Android应用程序的起点,它是由Linux内核的init进程创建的
Zygote的工作流程
提示:对看源码感到头疼的同学可以先看每段源码后面的结论,再根据自己的兴趣翻看对应源码
上面说到了真正执行的其实是/system/bin/目录下的app_process64程序(我的模拟器是64位的),它所对应的源代码是frameworks/base/cmds/app_process/app_main.cpp
app_main.cpp
#if defined(__LP64__)
static const char ABI_LIST_PROPERTY[] = "ro.product.cpu.abilist64";
static const char ZYGOTE_NICE_NAME[] = "zygote64";
#else
static const char ABI_LIST_PROPERTY[] = "ro.product.cpu.abilist32";
static const char ZYGOTE_NICE_NAME[] = "zygote";
#endif
int main(int argc, char* const argv[])
{
//...
bool zygote = false;
bool startSystemServer = false;
bool application = false;
String8 niceName;
String8 className;
//解析app_process的参数
while (i < argc) {
const char* arg = argv[i++];
if (strcmp(arg, "--zygote") == 0) {
zygote = true;
niceName = ZYGOTE_NICE_NAME;
} else if (strcmp(arg, "--start-system-server") == 0) {
startSystemServer = true;
} else if (strcmp(arg, "--application") == 0) {
application = true;
} else if (strncmp(arg, "--nice-name=", 12) == 0) {
niceName.setTo(arg + 12);
} else if (strncmp(arg, "--", 2) != 0) {
className.setTo(arg);
break;
} else {
--i;
break;
}
}
if (!niceName.isEmpty()) {
runtime.setArgv0(niceName.string());
//设置进程名称为“zygote”
set_process_name(niceName.string());
}
//args中存储的是关于虚拟机的参数,主要有start-system-server,abi-list,socket-name=zygote
if (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;
}
}
这个方法主要做了下面几件事情:
- 解析app_process的参数
- 设置当前进程名由app_process改为zygote
- 调用是
AndroidRuntime#start()
接下来程序就走到了frameworks\base\core\jni\AndroidRuntime.cpp
AndroidRuntime.cpp
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
static const String8 startSystemServer("start-system-server");
//...
JniInvocation jni_invocation;
jni_invocation.Init(NULL);
JNIEnv* env;
//启动虚拟机
if (startVm(&mJavaVM, &env, zygote) != 0) {
return;
}
onVmCreated(env);
//注册JNI函数
if (startReg(env) < 0) {
ALOGE("Unable to register all android natives\n");
return;
}
//...
char* slashClassName = toSlashClassName(className);
//这里的startClass就是com.android.internal.os.ZygoteInit
jclass startClass = env->FindClass(slashClassName);
if (startClass == NULL) {
ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
} else {
//反射调用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);
} else {
env->CallStaticVoidMethod(startClass, startMeth, strArray);
}
}
free(slashClassName);
}
这个方法主要做了下面几件事情:
- 启动虚拟机
- 注册JNI函数
- 调用
ZygoteInit.main()
方法
ZygoteInit
是java方法,从这里开始就从native世界进入到了java世界
ZygoteInit.java
public static void main(String argv[]) {
//创建ZygoteServer
ZygoteServer zygoteServer = new ZygoteServer();
//...
final Runnable caller;
try {
//...
boolean startSystemServer = false;
String socketName = "zygote";
String abiList = null;
boolean enableLazyPreload = false;
//解析app_main.cpp传来的参数
for (int i = 1; i < argv.length; i++) {
if ("start-system-server".equals(argv[i])) {
startSystemServer = true;
} else if ("--enable-lazy-preload".equals(argv[i])) {
enableLazyPreload = 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.");
}
//注册Zygote进程的socket通讯
zygoteServer.registerServerSocketFromEnv(socketName);
//...
//加载进程的资源和类
preload(bootTimingsTraceLog);
//...
if (startSystemServer) {
//创建SystemServer进程,这是zygote进程的第一次分裂
Runnable r = forkSystemServer(abiList, socketName, zygoteServer);
if (r != null) {
r.run();
return;
}
}
Log.i(TAG, "Accepting command socket connections");
//启动一个死循环监听来自Client端的消息
caller = zygoteServer.runSelectLoop(abiList);
} catch (Throwable ex) {
Log.e(TAG, "System zygote died with exception", ex);
throw ex;
} finally {
//关闭SystemServer的Socket
zygoteServer.closeServerSocket();
}
if (caller != null) {
caller.run();
}
}
这个方法主要做了下面几件事情:
- 预加载类和资源,包括颜色,R文件、drawable类等
- 创建
SystemServer
进程 - 创建
ZygoteServer
,开启一个死循环,等待着接收ActivityManagerService
的socket请求,即创建应用程序进程请求
SystemServer进程是一个非常重要的进程,我们来看看forkSystemServer()
是如何创建SystemServer
进程的
ZygoteInit.java
private static Runnable forkSystemServer(String abiList, String socketName,
ZygoteServer zygoteServer) {
//...
//真正创建SystemServer进程
int pid = Zygote.forkSystemServer(...);
if (pid == 0) {
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}
zygoteServer.closeServerSocket();
//继续方法调用
return handleSystemServerProcess(parsedArgs);
}
return null;
}
fork()
函数是一次执行,两次返回。说的更严谨一点是 两个进程对用一个程序的两次执行。当pid == 0
时,说明现在处于子进程,当pid > 0
时,说明处于父进程
ZygoteInit.java
private static Runnable handleSystemServerProcess(ZygoteConnection.Arguments parsedArgs) {
//....
return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
}
ZygoteInit.java
public static final Runnable zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) {
//常规的一些初始化,比如日志输出、未捕获异常处理等
RuntimeInit.commonInit();
//主要用于初始化binder机制,并启动一个binder线程(用于SystemServer与其他进程通信)
ZygoteInit.nativeZygoteInit();
//调用SystemServer.java的入口函数
return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
}
所以forkSystemServer()
主要做了下面几件事:
- 创建
SystemServer
进程 - 一些常规初始化
- 初始化Binder机制,用于
SystemServer
与其他进程的通信(如应用进程、ServiceManager
进程等) - 调用
SystemServer.java
的入口函数
SystemServer.mian()
直接调用了SystemServer#run()
方法
SystemServer.java
private void run() {
//...
//为主线程创建Looper
Looper.prepareMainLooper();
//加载共享库,即系统服务的native层代码
System.loadLibrary("android_servers");
//创建上下文
createSystemContext();
//...
//启动ActivityManagerService、SystemServiceManager、DisplayManagerService、
//PackageManagerService、WindowManager等
startBootstrapServices();
startCoreServices();
//开始准备HomeActivity的前奏工作,并通过Intent唤起桌面应用
startOtherServices();
//...
// Loop forever.
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
下面放一张图概括一下上面的整个过程
android系统启动过程总结
回到我们最初的问题
每一个应用进程和虚拟机,都是由谁创建的呢?
由Zygote进程创建
应用进程创建的时机又是怎么样的呢?
当Activity需要被启动的时候,SystemServer中负责管理进程的AMS利用Socket客户端向Zygote的Socket服务端发送创建新进程命令,Zygote收到命令后为应用创建进程,这是典型的C/S架构
如何尽量减少创建一个新的进程的性能损耗呢?
每个应用进程不仅有自己的数据资源和需要执行的代码,还需要用到Android框架中通用的资源和代码,由于这些资源和代码是大部分应用都需要调用到的,并且比较重量级,所以安卓把它们都放在Zygote进程的空间中,而应用进程又是继承于Zygote进程,所以当应用需要的时候就直接到里面去找就行了
本文主要讲了系统启动的流程,但是我们实际上并没有对Activity是如何被启动的做深入的分析,所以对Activity启动流程感兴趣的可以看Activity启动流程
网友评论