当摁住电源键,引导芯片代码开始从固化在ROM中预定义的地方开始执行,加载引导程序Bootloader到RAM,然后执行引导程序。
Bootloader引导程序是Android操作系统被拉起来之前的一个程序,类似于window一样,它的作用就是把系统拉起运行起来,然后启动内核。
内核启动会设置缓存、被保护存储器、计划列表,加载驱动。当内核完成系统设置,它首先在系统文件中寻找”init”文件,然后启动init进程。
Init 进程解析init.rc脚本
Init 进程启动之后会挂载文件系统、再挂载相应的分区,启动SELinux安全策略,启动属性服务,解析init.rc脚本,并启动相应属性服务进程 。
zygote 进程的启动就在init.rc脚本中 。
源码点这 zygote64.rc
- service zygote: 表示 Zygote 进程是以服务的形式启动的
- /system/bin/app_process64: 表示 Zygote 进程的应用程序文件
- 后面四个选项表示 Zygote 进程的启动参数
- –start-system-server: 表示在 Zygote 进程启动过程中, 需要启动 System 进程
- socket zygote stream 660 root system: 表示 Zygote 进程启动过程中需要创建一个名为 zygote 的 Socket
- 这个 Socket 的用于执行进程间的通信
- 访问权限为 660 root system, 即所有用户都可以对它进行读写
调用Zygote 进程main方法
Zygote 的入口在 /system/bin/app_process64 目录下 , 最终会调用到
\frameworks\base\cmds\app_process\app_main.cpp 中main方法 , main 方法中有个关键代码runtime.start("com.android.internal.os.ZygoteInit", args, zygote) , 通过runtime来启动zygote 。
runtime 为 AppRuntime , 继承自AndroidRuntime类,重载了AndroidRuntime类的onVmCreated()、onStarted()、onZygoteInit()和onExit()函数,是zygote进程处理时实际runtime入口。
AndroidRumtime主要功能:
- 创建并启动JAVA虚拟机。
- 注册JNI 方法 。
- 开启JAVA世界。
AndroidRuntime#start 方法 , 创建JVM虚拟机并启动。
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
//创建jvm虚拟机
JniInvocation jni_invocation;
jni_invocation.Init(NULL);
JNIEnv* env;
if (startVm(&mJavaVM, &env, zygote) != 0) {
return;
}
onVmCreated(env);
}
JniInvocation,是一个外部和虚拟机之间的一个中间层,是外部访问虚拟机的API接口,允许外部动态的调用虚拟机内部的实现。其主要实现如下功能: 指定加载的虚拟机。现在Android系统中有两种虚拟机:dalvik和art。现在已基本使用art虚拟机了。
我们再来看下对jni方法的处理,在AndroidRuntime 可以看到定义了很多jni方法。
我们来看下是怎么注册jni方法的 。
在jvm创建好之后,会调用startReg方法。
/*static*/ int AndroidRuntime::startReg(JNIEnv* env)
{
androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc);
ALOGV("--- registering native functions ---\n");
env->PushLocalFrame(200);
if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
env->PopLocalFrame(NULL);
return -1;
}
env->PopLocalFrame(NULL);
return 0;
}
gRegJNI 为 上图定义的jni方法 , 调用register_jni_procs注册定义好的jni方法。
总结一下 : native的zygote 启动主要功能都交给AndroidRuntime 处理 ,AndroidRuntime 先创建JVM 虚拟机 , 然后注册JNI方法 。
完成了JVM的创建以及JNI方法注册 , 就可以去到JAVA的世界了 。 在AndroidRuntime#start 方法末尾。
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
JniInvocation jni_invocation;
jni_invocation.Init(NULL);
JNIEnv* env;
if (startVm(&mJavaVM, &env, zygote) != 0) {
return;
}
onVmCreated(env);
if (startReg(env) < 0) {
ALOGE("Unable to register all android natives\n");
return;
}
jclass stringClass;
jobjectArray strArray;
jstring classNameStr;
stringClass = env->FindClass("java/lang/String");
strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);
//className = com.android.internal.os.ZygoteInit
classNameStr = env->NewStringUTF(className);
env->SetObjectArrayElement(strArray, 0, classNameStr);
for (size_t i = 0; i < options.size(); ++i) {
jstring optionsStr = env->NewStringUTF(options.itemAt(i).string());
assert(optionsStr != NULL);
env->SetObjectArrayElement(strArray, i + 1, optionsStr);
}
char* slashClassName = toSlashClassName(className != NULL ? className : "");
jclass startClass = env->FindClass(slashClassName);
if (startClass == NULL) {
} else {
jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
"([Ljava/lang/String;)V");
env->CallStaticVoidMethod(startClass, startMeth, strArray);
}
}
env->CallStaticVoidMethod , 调用 java层 com.android.internal.os.ZygoteInit 的 main 方法 , 打开java世界的大门 , 我们来看下ZygoteInit的main方法 。
Java层ZygoteInit#main方法
ZygoteInit #main方法主要做三歩
- 创建用于通信的socket
- fork SystemServer 进程
- 调用runSelectLoopMode 沉睡 ,当接收到子孙后代的请求时,它会随时醒来,为它们工作,为它们创建一个进程。
public static void main(String argv[]) {
ZygoteServer zygoteServer = null;
ZygoteHooks.startZygoteNoThreadCreation();
Runnable caller;
try {
final boolean isPrimaryZygote = zygoteSocketName.equals(Zygote.PRIMARY_SOCKET_NAME);
//创建socket 服务端
zygoteServer = new ZygoteServer(isPrimaryZygote);
if (startSystemServer) {
// fork system server 进程
Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
// r == nul 表示在zygote进程中
if (r != null) {
//在system_server进程中直接 return
r.run();
return;
}
}
// 沉睡 ,等待唤醒
caller = zygoteServer.runSelectLoop(abiList);
} catch (Throwable ex) {
throw ex;
} finally {
if (zygoteServer != null) {
//关闭socket
zygoteServer.closeServerSocket();
}
}
if (caller != null) {
//在子进程中 , 并且退出了select loop执行
caller.run();
}
}
SystemServer 进程的启动以后讲。
总结
Init 进程通过解析init.rc脚本在native层创建了Zygote进程 ,zygote在native层中创建java层需要的 JVM 虚拟机 和 注册了用于与Native层通信的JNI 方法, 最后调用zygote 在JAVA层的main 方法 。
zygote java 层的 main 方法中 初始化了用于通信的socket 服务端 ,然后 fork SystemServer进程并启动。 参考文章: