android zygote进程启动流程
Init进程启动后,最重要的一个进程就是Zygote进程,SystemServer和其他所有Dalivik虚拟机进程都是由Zygote fork而来。Zygote进程由app_process启动,Zygote是一个C/S模型,Zygote进程作为服务端,其他进程作为客户端向它发出“孵化-fork”请求,而Zygote接收到这个请求后就“孵化-fork”出一个新的进程。
Android系统启动篇
4,《Android SystemServer进程启动流程》
Android系统开发准备篇
3,《Android Framework代码IDE加载和调试》
Android系统开发实践篇
4,《android单独编译framework模块并push》
Android系统开发核心知识储备篇
1,《Android编译系统-envsetup和lunch代码篇》
6,《Android中Activity、View和Window关系详解》
11,《android中AMS进程通知Zygote进程fork新进程的通信方式》
Android核心功能详解篇
2,《Android 手势导航(从下往上滑动进入多任务页面)》
3,《android手势分析(应用界面左往右边滑动退出应用)》
———————————————————————————————————————————
目录
一,背景介绍
Init进程启动后,最重要的一个进程就是Zygote进程,SystemServer和其他所有Dalivik虚拟机进程都是由Zygote fork而来。Zygote进程由app_process启动,Zygote是一个C/S模型,Zygote进程作为服务端,其他进程作为客户端向它发出“孵化-fork”请求,而Zygote接收到这个请求后就“孵化-fork”出一个新的进程。由于Zygote进程在启动时会创建Java虚拟机,因此通过fork而创建的应用程序进程和SystemServer进程可以在内部获取一个Java虚拟机的实例拷贝。
在system/core/rootdir/init.zygote64.rc文件中,启动zygote进程如下,
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
init进程就是通过这个service名称来创建zygote进程,zygote这个服务,通过执行进行/system/bin/app_process64 并传入4个参数进行运行,创建一个子进程,参数说明如下,
1,-Xzygote 该参数将作为虚拟机启动时所需的参数
2,/system/bin 代表虚拟机程序所在目录
3,--zygote 指明以ZygoteInit.java类中的main函数作为虚拟机执行入口
4,--start-system-server 告诉Zygote进程启动systemServer进程
二,启动流程
2.1 启动入口
路径:frameworks/base/cmds/app_process/app_main.cpp
int main(int argc, char* const argv[])
{
---------------------------------------------------------------
//zygote传入的参数argv为“-Xzygote /system/bin --zygote --start-system-server --socket-name=zygote”
//zygote_secondary传入的参数argv为“-Xzygote /system/bin --zygote --socket-name=zygote_secondary”
...
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) {
//是否需要启动system server
startSystemServer = true;
} else if (strcmp(arg, "--application") == 0) {
//启动进入独立的程序模式
application = true;
} else if (strncmp(arg, "--nice-name=", 12) == 0) {
//niceName 为当前进程别名,区别abi型号
niceName.setTo(arg + 12);
} else if (strncmp(arg, "--", 2) != 0) {
className.setTo(arg);
break;
} else {
--i;
break;
}
}
..
if (!className.isEmpty()) { //className不为空,说明是application启动模式
...
} else {
//进入zygote模式,新建Dalvik的缓存目录:/data/dalvik-cache
maybeCreateDalvikCache();
if (startSystemServer) { //加入start-system-server参数
args.add(String8("start-system-server"));
}
String8 abiFlag("--abi-list=");
abiFlag.append(prop);
args.add(abiFlag); //加入--abi-list=参数
// In zygote mode, pass all remaining arguments to the zygote
// main() method.
for (; i < argc; ++i) { //将剩下的参数加入args
args.add(String8(argv[i]));
}
}
...
if (!niceName.isEmpty()) {
runtime.setArgv0(niceName.string(), true /* setProcName */);
}
if (zygote) { //如果是zygote启动模式,则加载ZygoteInit
runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
} else if (className) { //如果是application启动模式,则加载RuntimeInit
runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
} else {
//没有指定类名或zygote,参数错误
fprintf(stderr, "Error: no class name or --zygote supplied.\n");
app_usage();
LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
}
------------------------------------------------
}
首先是解析传入的启动参数,根据--zygote参数,来确认执行那个方法,这里有两种情况
1,执行ZygoteInit,也就是去初始化zygote进程
2,执行RuntimeInit,这里其实就是启动普通应用程序
我们现在是初次启动,会走入第一个分支,也就是去执行ZygoteInit,可以看到,这里是通过runtime变量去调用start方法,实际上调用的是其父类AndroidRuntime的start方法
2.2 AndroidRuntime
路径:frameworks/base/core/jni/AndroidRuntime.cpp
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
ALOGD(">>>>>> START %s uid %d <<<<<<\n",
className != NULL ? className : "(unknown)", getuid());
static const String8 startSystemServer("start-system-server");
//判断是否是启动systemServer
for (size_t i = 0; i < options.size(); ++i) {
if (options[i] == startSystemServer) {
/* track our progress through the boot sequence */
const int LOG_BOOT_PROGRESS_START = 3000;
LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START, ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
}
}
//从环境变量ANDROID_ROOT中读取系统目录
const char* rootDir = getenv("ANDROID_ROOT");
if (rootDir == NULL) {
rootDir = "/system";
if (!hasDir("/system")) {
LOG_FATAL("No root directory specified, and /android does not exist.");
return;
}
setenv("ANDROID_ROOT", rootDir, 1);
}
//const char* kernelHack = getenv("LD_ASSUME_KERNEL");
//ALOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack);
/* start the virtual machine */
JniInvocation jni_invocation;
//初始化jni接口
jni_invocation.Init(NULL);
JNIEnv* env;
//启动虚拟机
if (startVm(&mJavaVM, &env, zygote) != 0) {
return;
}
//这里实际上调用的子类的重写方法,也就是前面app_main.cpp中的AppRuntime
onVmCreated(env);
//...省略以下代码,主要去调用上面的java方法Zygoteinit
}
整体来看,经历了以下几个步骤
1,判断是否启动SystemSever
2,从环境变量ANDROID_ROOT中读取系统目录
3,初始化jni接口,并启动虚拟机
4,启动Zygoteinit类的main()函数
2.3 Zygoteinit
路径:frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public static void main(String argv[]) {
ZygoteServer zygoteServer = new ZygoteServer();
// Mark zygote start. This ensures that thread creation will throw
// an error.
ZygoteHooks.startZygoteNoThreadCreation();
// Zygote goes into its own process group.
try {
Os.setpgid(0, 0);
} catch (ErrnoException ex) {
throw new RuntimeException("Failed to setpgid(0,0)", ex);
}
final Runnable caller;
try {
// Report Zygote start time to tron unless it is a runtime restart
//...
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.");
}
//注册一个Socket
zygoteServer.registerServerSocketFromEnv(socketName);
// In some configurations, we avoid preloading resources and classes eagerly.
// In such cases, we will preload things prior to our first fork.
//判断是否需要预加载
if (!enableLazyPreload) {
bootTimingsTraceLog.traceBegin("ZygotePreload");
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
SystemClock.uptimeMillis());
//预加载各种资源类
preload(bootTimingsTraceLog);
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
SystemClock.uptimeMillis());
bootTimingsTraceLog.traceEnd(); // ZygotePreload
} else {
Zygote.resetNicePriority();
}
//...
if (startSystemServer) {
//启动SystemServer
Runnable r = forkSystemServer(abiList, socketName, zygoteServer);
// {@code r == null} in the parent (zygote) process, and {@code r != null} in the
// child (system_server) process.
if (r != null) {
r.run();
return;
}
}
caller = zygoteServer.runSelectLoop(abiList);
} catch (Throwable ex) {
Log.e(TAG, "System zygote died with exception", ex);
throw ex;
} finally {
zygoteServer.closeServerSocket();
}
...
}
从上面看出,Zygote的主函数其实不复杂,主要完成了以下工作
- 注册一个Socket
当有新程序需要时,系统会通过这个socket在第一时间通知ZygoteServer - 预加载各类资源
通过preload函数,加载虚拟机运行时需要的各类资源
2.4 启动SystemServer
当启动zygote时,启动参数里面带有--start-system-server
时,便会调用forkSystemServer来创建SystemServer,看下这个函数的实现:
private static Runnable forkSystemServer(String abiList, String socketName,
ZygoteServer zygoteServer) {
//...
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",
"--capabilities=" + capabilities + "," + capabilities,
"--nice-name=system_server",
"--runtime-args",
"--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
"com.android.server.SystemServer",
};
ZygoteConnection.Arguments parsedArgs = null;
int pid;
try {
parsedArgs = new ZygoteConnection.Arguments(args);
ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);
boolean profileSystemServer = SystemProperties.getBoolean(
"dalvik.vm.profilesystemserver", false);
if (profileSystemServer) {
parsedArgs.runtimeFlags |= Zygote.PROFILE_SYSTEM_SERVER;
}
//通过这个函数去fork一个新的进程
pid = Zygote.forkSystemServer(
parsedArgs.uid, parsedArgs.gid,
parsedArgs.gids,
parsedArgs.runtimeFlags,
null,
parsedArgs.permittedCapabilities,
parsedArgs.effectiveCapabilities);
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}
/* For child process */
if (pid == 0) {
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}
zygoteServer.closeServerSocket();
return handleSystemServerProcess(parsedArgs);
}
return null;
}
上述代码通过调用Zygote.forkSystemServer去创建了一个新进程(具体的fork流程后续再出文章分析),并返回pid,而当pid=0
时,将去执行handleSystemServerProcess,继续看这个函数的实现
private static Runnable handleSystemServerProcess(ZygoteConnection.Arguments parsedArgs) {
// set umask to 0077 so new files and directories will default to owner-only permissions.
//...
final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
if (systemServerClasspath != null) {
//...
} else {
ClassLoader cl = null;
if (systemServerClasspath != null) {
cl = createPathClassLoader(systemServerClasspath, parsedArgs.targetSdkVersion);
Thread.currentThread().setContextClassLoader(cl);
}
/*
* Pass the remaining arguments to SystemServer.
*/
return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
}
/* should never reach here */
}
这里实际上是去调用ZygoteInit.zygoteInit
public static final Runnable zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) {
if (RuntimeInit.DEBUG) {
Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");
}
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
RuntimeInit.redirectLogStreams();
//初始化通用部分
RuntimeInit.commonInit();
//初始化native函数
ZygoteInit.nativeZygoteInit();
//初始化Application
return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
}
在这里有三个初始化函数:
1,commonInit初始化通用部分
2,nativeZygoteInit初始化native部分的服务,内部去调用startThreadPool开启了Binder线程池,保证其他进程能正确访问到zygote
3,applicationInit初始化java服务部分,函数内部根据前面传入的参数,找到SystemServer的main方法,并调用
通过上述步骤,Zygote成功打开了虚拟机,最后去调用SystemServer的main方法。
更多推荐
所有评论(0)