Android5.0开关机模块——zygote进程
前面两篇一直在介绍init进程的内容,这一节介绍Android最重要的一个进程zygote,zygote翻译成中文就是受精卵、孵化器的意思,换言之,Android的framework层和其他的进程都是由它孵化出来的,可想而知有多么的重要。
zygote在init.rc中的描述如下,
service 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
从参数中可以看出,zygote进程程序位于/system/bin/app_process,代码位于/framework/base/cmds/app_process/app_main.cpp中
它的main函数很简单,主要完成以下几件事情,
定义一个runtime用来跑虚拟机,因为后面要运行java代码,必然要跑虚拟机
AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
解析传进来的参数
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()); set_process_name(niceName.string()); }
运行zygoteinit
if (zygote) { runtime.start("com.android.internal.os.ZygoteInit", args); } else if (className) { runtime.start("com.android.internal.os.RuntimeInit", args); } 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; }
runtime.start的定义是
void AndroidRuntime::start(const char* className, const Vector& options)
这个函数的作用是启动Android系统运行时库,它主要做了三件事情,一是调用函数startVM启动虚拟机,二是调用函数startReg注册JNI方法,三是调用了com.android.internal.os.ZygoteInit类的main函数。我们重点关注zygote的main方法
if (startVm(&mJavaVM, &env) != 0) { return; }
if (startReg(env) < 0) { ALOGE("Unable to register all android natives\n"); return; }
/* * Start VM. This thread becomes the main thread of the VM, and will * not return until the VM exits. */ char* slashClassName = toSlashClassName(className); jclass startClass = env->FindClass(slashClassName); if (startClass == NULL) { ALOGE("JavaVM unable to locate class '%s'\n", slashClassName); /* keep going */ } else { 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);#if 0 if (env->ExceptionCheck()) threadExitUncaughtException(env);#endif } }
因为zygoteinit是java代码,所以上面要启动VM
zygoteinit的main函数主要作了三件事情,
一个调用registerZygoteSocket函数创建了一个socket接口,用来和ActivityManagerService通讯
registerZygoteSocket(socketName); EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START, SystemClock.uptimeMillis()); preload(); EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END, SystemClock.uptimeMillis());
private static void registerZygoteSocket(String socketName) { if (sServerSocket == null) { int fileDesc; final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName; try { String env = System.getenv(fullSocketName); fileDesc = Integer.parseInt(env); } catch (RuntimeException ex) { throw new RuntimeException(fullSocketName + " unset or invalid", ex); } try { sServerSocket = new LocalServerSocket( createFileDescriptor()); } catch (IOException ex) fileDesc{ throw new RuntimeException( "Error binding to local socket '" + fileDesc + "'", ex); } } }
这个socket接口是通过文件描述符来创建的,这个文件描符代表的就是我们前面说的/dev/socket/zygote文件了。这个文件描述符是通过环境变量ANDROID_SOCKET_ENV得到的。这个环境变量的值又是由谁来设置的呢?我们知道,系统启动脚本文件system/core/rootdir/init.rc是由init进程来解释执行的,而init进程的源代码位于system/core/init目录中,在init.c文件中,是由service_start函数来解释init.rc文件中的service命令的。每一个service命令都会促使init进程调用fork函数来创建一个新的进程,在新的进程里面,会分析里面的socket选项,对于每一个socket选项,都会通过create_socket函数来在/dev/socket目录下创建一个文件,在这个场景中,这个文件便是zygote了,然后得到的文件描述符通过publish_socket函数写入到环境变量中去 因此,这里就把上面得到的文件描述符写入到以"ANDROID_SOCKET_zygote"为key值的环境变量中。又因为上面的ZygoteInit.registerZygoteSocket函数与这里创建socket文件的create_socket函数是运行在同一个进程中,因此,上面的ZygoteInit.registerZygoteSocket函数可以直接使用这个文件描述符来创建一个Java层的LocalServerSocket对象。如果其它进程也需要打开这个/dev/socket/zygote文件来和Zygote进程进行通信,那就必须要通过文件名来连接这个LocalServerSocket了
二是预加载
static void preload() { Log.d(TAG, "begin preload"); preloadClasses(); preloadResources(); preloadOpenGL(); preloadSharedLibraries(); // Ask the WebViewFactory to do any initialization that must run in the zygote process, // for memory sharing purposes. WebViewFactory.prepareWebViewInZygote(); Log.d(TAG, "end preload"); }
三是调用startSystemServer函数来启动SystemServer组件,
四是调用runSelectLoopMode函数进入一个无限循环在前面创建的socket接口上等待ActivityManagerService请求创建新的应用程序进程。
至此,zygote进程就结束了,它会一直循环在这里,等待其他进程请求它孵化出新的进程。
在startSystemServer中,会创建一个新的子进程来执行handleSystemServerProcess
private static boolean startSystemServer(String abiList, String socketName) throws MethodAndArgsCaller, RuntimeException { long capabilities = posixCapabilitiesAsBits( OsConstants.CAP_BLOCK_SUSPEND, OsConstants.CAP_KILL, OsConstants.CAP_NET_ADMIN, OsConstants.CAP_NET_BIND_SERVICE, OsConstants.CAP_NET_BROADCAST, OsConstants.CAP_NET_RAW, OsConstants.CAP_SYS_MODULE, OsConstants.CAP_SYS_NICE, OsConstants.CAP_SYS_RESOURCE, OsConstants.CAP_SYS_TIME, OsConstants.CAP_SYS_TTY_CONFIG ); /* Hardcoded command line to start the system server */ String args[] = { "--setuid=1000", "--setgid=1000", "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1032,3001,3002,3003,3006,3007", "--capabilities=" + capabilities + "," + capabilities, "--runtime-init", "--nice-name=system_server", "com.android.server.SystemServer", }; ZygoteConnection.Arguments parsedArgs = null; int pid; try { parsedArgs = new ZygoteConnection.Arguments(args); ZygoteConnection.applyDebuggerSystemProperty(parsedArgs); ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs); /* Request to fork the system server process */ 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) { if (hasSecondZygote(abiList)) { waitForSecondaryZygote(socketName); } handleSystemServerProcess(parsedArgs); } return true; }
private static void handleSystemServerProcess( ZygoteConnection.Arguments parsedArgs) throws ZygoteInit.MethodAndArgsCaller { closeServerSocket(); // set umask to 0077 so new files and directories will default to owner-only permissions. Os.umask(S_IRWXG | S_IRWXO); if (parsedArgs.niceName != null) { Process.setArgV0(parsedArgs.niceName); } final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH"); if (systemServerClasspath != null) { performSystemServerDexOpt(systemServerClasspath); } if (parsedArgs.invokeWith != null) { String[] args = parsedArgs.remainingArgs; // If we have a non-null system server class path, we'll have to duplicate the // existing arguments and append the classpath to it. ART will handle the classpath // correctly when we exec a new process. if (systemServerClasspath != null) { String[] amendedArgs = new String[args.length + 2]; amendedArgs[0] = "-cp"; amendedArgs[1] = systemServerClasspath; System.arraycopy(parsedArgs.remainingArgs, 0, amendedArgs, 2, parsedArgs.remainingArgs.length); } WrapperInit.execApplication(parsedArgs.invokeWith, parsedArgs.niceName, parsedArgs.targetSdkVersion, null, args); } else { ClassLoader cl = null; if (systemServerClasspath != null) { cl = new PathClassLoader(systemServerClasspath, ClassLoader.getSystemClassLoader()); Thread.currentThread().setContextClassLoader(cl); } /* * Pass the remaining arguments to SystemServer. */ RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl); } /* should never reach here */ }
重点是zygoteinit
public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) throws ZygoteInit.MethodAndArgsCaller { if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote"); redirectLogStreams(); commonInit(); nativeZygoteInit(); applicationInit(targetSdkVersion, argv, classLoader); }
这个函数都是做一些初始化工作,其中nativeZygoteInit最终会调用到app_main.cpp中的onZygoteInit
virtual void onZygoteInit() { // Re-enable tracing now that we're no longer in Zygote. atrace_set_tracing_enabled(true); sp proc = ProcessState::self(); ALOGV("App process: starting thread pool.\n"); proc->startThreadPool(); }
applicationInit函数中的invokeStaticMain(args.startClass, args.startArgs, classLoader);最终会调用SystemServer.java中的main函数
/** * The main entry point from zygote. */ public static void main(String[] args) { new SystemServer().run(); }
关于systemserver的内容,下节再谈
更多相关文章
- android studio中断开SVN连接,并彻底清理项目中的.svn文件
- 第二十篇 Android获取本机图片、音频、视频、文档以及本地文件夹
- Android中资源文件用法简单示例
- Unity3d导出Android的apk文件时相关问题的解决办法
- android编译系统的makefile文件Android.mk写法
- android文件系统挂载分析
- Android 自定义文件路径选择器
- Android studio怎样添加assets文件