Android5.0源码分析—— Zygote进程分析
1 Zygote简介
Android的应用程序一般都是由Java语言编写而成的,这样的应用程序需要运行在独自的Dalvik虚拟机之上(当然,5.0好像默认了ART了)。但是,如果在每一个进程启动时都在物理内存中创建和初始化一个Dalvik虚拟机,这无疑对系统的性能造成很大的影响。Zygote是Android系统中的一个非常重要的守护进程,所有其他应用程序的Dalvik虚拟机都是通过Zygote孵化出来的。通过这种方式,虚拟机的内存和框架层的资源被所有应用程序共享,从而提高了应用程序的启动和运行速度。下图为Android启动的大致流程。
图1. Android系统启动的大致流程
2 Zygote启动流程分析
2.1 Init进程分析
int main(int argc, char **argv) { …… //创建并挂载了一些基本的系统文件 mkdir("/dev", 0755); mkdir("/proc", 0755); mkdir("/sys", 0755); mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755"); mkdir("/dev/pts", 0755); mkdir("/dev/socket", 0755); mount("devpts", "/dev/pts", "devpts", 0, NULL); mount("proc", "/proc", "proc", 0, NULL); mount("sysfs", "/sys", "sysfs", 0, NULL); …… //初始化了部分属性 property_init(); …… property_load_boot_defaults(); //加载了启动配置文件,即init.rc文件 init_parse_config_file("/init.rc"); //触发Action action_for_each_trigger("early-init", action_add_queue_tail); queue_builtin_action(wait_for_coldboot_done_action, "wait_for_coldboot_done"); queue_builtin_action(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng"); queue_builtin_action(keychord_init_action, "keychord_init"); queue_builtin_action(console_init_action, "console_init"); …… queue_builtin_action(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng"); queue_builtin_action(property_service_init_action, "property_service_init"); queue_builtin_action(signal_init_action, "signal_init"); …… for(;;) { int nr, i, timeout = -1; execute_one_command();//执行当前Command中的一个命令,Action和Service被启动 restart_processes(); //重新启动设置了重新启动标志位的进程 //监听来自属性服务的事件 if (!property_set_fd_init && get_property_set_fd() > 0) { ufds[fd_count].fd = get_property_set_fd(); ufds[fd_count].events = POLLIN; ufds[fd_count].revents = 0; fd_count++; property_set_fd_init = 1; } //监控singal,如果子进程异常退出,内核将抛出SIGCHILD信号,此时将可以对进程进行处理 //或是回收系统资源,或是重启子进程 if (!signal_fd_init && get_signal_fd() > 0) { ufds[fd_count].fd = get_signal_fd(); ufds[fd_count].events = POLLIN; ufds[fd_count].revents = 0; fd_count++; signal_fd_init = 1; } //监听来自keychord设备的事件,这是个组合按键设备 if (!keychord_fd_init && get_keychord_fd() > 0) { ufds[fd_count].fd = get_keychord_fd(); ufds[fd_count].events = POLLIN; ufds[fd_count].revents = 0; fd_count++; keychord_fd_init = 1; } …… nr = poll(ufds, fd_count, timeout);//利用poll监听以上事件 if (nr <= 0) continue; for (i = 0; i < fd_count; i++) { if (ufds[i].revents & POLLIN) { if (ufds[i].fd == get_property_set_fd()) handle_property_set_fd();//处理属性服务相关事件 else if (ufds[i].fd == get_keychord_fd()) handle_keychord();//处理keychord事件 else if (ufds[i].fd == get_signal_fd()) handle_signal();//处理singal事件 } } } return 0; |
Zygote作为一个服务也被定义在了init.rc文件中,由init进程派生出来,配置代码截取在如下:
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是由java的服务进程,其启动过程和其他在init.rc文件中定义的service启动不太一样。
2.2 App_main.cpp
通过配置信息可以定位Zygote的入口函数为app_main.cpp中的main,其代码截取如下:
int main(int argc, char* const argv[]) { …… //此类是AndroidRuntime的派生类 AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv)); …… while (i < argc) {//遍历Zygote的配置参数 const char* arg = argv[i++]; if (strcmp(arg, "--zygote") == 0) {//为进程更换名字 zygote = true; niceName = ZYGOTE_NICE_NAME; } else if (strcmp(arg, "--start-system-server") == 0) {//设置systemServer为true startSystemServer = true; } else if (strcmp(arg, "--application") == 0) {//设置application启动为true application = true; } else if (strncmp(arg, "--nice-name=", 12) == 0) { …… } } …… if (zygote) {//如果配置参数中有参数显示需要启动Zygote,则ZygoteInit启动 runtime.start("com.android.internal.os.ZygoteInit", args); } else if (className) {//否则RuntimeInit启动 runtime.start("com.android.internal.os.RuntimeInit", args); } else { …… } } |
1)runtime.start("com.android.internal.os.ZygoteInit",args)
2)runtime.start("com.android.internal.os.RuntimeInit",args)
因此可能存在两种不同的启动方式, “RuntimeInit”式启动时序大致如下图所示:
void AndroidRuntime::start(const char* className, const Vector<String8>& options) { ……//配置虚拟机的一些参数 JniInvocation jni_invocation; jni_invocation.Init(NULL); JNIEnv* env; //开启虚拟机 if (startVm(&mJavaVM, &env) != 0) { return; } //这里实际上是调用了子类AppRuntime的onVmCreate(env) onVmCreated(env); //注册Android JNI函数 if (startReg(env) < 0) { ALOGE("Unable to register all android natives\n"); return; } //在开始调用main之前需要将参数转化成java可识别的类型,并将其全部存入一个数组 jclass stringClass; jobjectArray strArray; jstring classNameStr; stringClass = env->FindClass("java/lang/String"); assert(stringClass != NULL); strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL); assert(strArray != NULL); classNameStr = env->NewStringUTF(className); assert(classNameStr != NULL); 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); //找到需要启动的java类 jclass startClass = env->FindClass(slashClassName); if (startClass == NULL) { ALOGE("JavaVM unable to locate class '%s'\n", slashClassName); } else { //得到指定类中指定方法的ID,这里得到的是ZygoteInit.main()的方法ID jmethodID startMeth = env->GetStaticMethodID(startClass, "main", "([Ljava/lang/String;)V"); if (startMeth == NULL) { ALOGE("JavaVM unable to find main() in '%s'\n", className); } else { //调用上面得到的方法ID和相关参数,即调用Java类ZygoteInit.main(); env->CallStaticVoidMethod(startClass, startMeth, strArray); …… } } ……//回收资源关闭虚拟机等操作,这个函数除非进程退出,否则不会返回 } |
AndroidRuntime.start()实际上主要做了3件事:1,startVM开启虚拟机;2,startReg()注册了JNI方法;3,调用Java方法。
2.3 ZygoteInit分析
根据init.rc中Zygote的配置参数,AndroidRuntime.start()最终调用的是ZgoteInit.main()。其代码截取如下:
public static void main(String argv[]) { try { …… registerZygoteSocket(socketName);//初始化了server(zygote)的一个localsocket EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START, SystemClock.uptimeMillis()); preload();//加载了framwork.jar的class和资源到内存,这部分很占CPU EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END, SystemClock.uptimeMillis()); SamplingProfilerIntegration.writeZygoteSnapshot(); gc();//由于后续需要fork出应用程序的进程,需要进行垃圾回收以确保应用程序的性能 Trace.setTracingEnabled(false); if (startSystemServer) { startSystemServer(abiList, socketName);//开启System server服务 } Log.i(TAG, "Accepting command socket connections"); runSelectLoop(abiList);//开启循环 closeServerSocket(); } catch (MethodAndArgsCaller caller) { caller.run();//这里实际上是真正开启了systemServer进程 } catch (RuntimeException ex) { Log.e(TAG, "Zygote died with exception", ex); closeServerSocket(); throw ex; } } |
2.4 Zygote启动SystemServer服务简要分析
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 ); //SystemServer的启动参数设置 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); //向Zygote发送fork请求 pid = Zygote.forkSystemServer( parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, parsedArgs.debugFlags, null, parsedArgs.permittedCapabilities, parsedArgs.effectiveCapabilities); } catch (IllegalArgumentException ex) { throw new RuntimeException(ex); } //以下代码仅对子进程SystemServer有效 if (pid == 0) { if (hasSecondZygote(abiList)) { waitForSecondaryZygote(socketName); } handleSystemServerProcess(parsedArgs); } return true; } |
private static void handleSystemServerProcess( ZygoteConnection.Arguments parsedArgs) throws ZygoteInit.MethodAndArgsCaller { closeServerSocket(); //设置默认权限 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 (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); } //将余下的参数传递给RuntimeInit.zygoteInit处理 RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl); } //永远不会执行到这里 } |
public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) throws ZygoteInit.MethodAndArgsCaller { if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote"); //重定向log redirectLogStreams(); //初始化运行环境 commonInit(); //启动binder线程池 nativeZygoteInit(); //调用应用程序的入口函数 applicationInit(targetSdkVersion, argv, classLoader); } |
private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) throws ZygoteInit.MethodAndArgsCaller{ nativeSetExitWithoutCleanup(true); …… invokeStaticMain(args.startClass, args.startArgs, classLoader); } |
private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader) throws ZygoteInit.MethodAndArgsCaller { //解析类名 Class<?> cl; try { cl = Class.forName(className, true, classLoader); } catch (ClassNotFoundException ex) { throw new RuntimeException( "Missing class when invoking static main " + className, ex); } //解析main方法 Method m; try { 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); } int modifiers = m.getModifiers(); if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) { throw new RuntimeException( "Main method is not public and static on " + className); } //这里并没有直接去调用SystemServer.main()而是抛出了一个异常,这个异常将在//ZygoteInit.main()中被捕捉 throw new ZygoteInit.MethodAndArgsCaller(m, argv); } |
public static class MethodAndArgsCaller extends Exception implements Runnable { //调用方法体 private final Method mMethod; //调用方法所需要的参数 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); } } } } |
2.5 runSelectLoop()分析
之前已经描述,Zygote在建立ServerSystem服务之后一直处于runSelectLoop循环中,等待AMS的fork请求,runSelectLoop代码截取如下:
private static void runSelectLoop(String abiList) throws MethodAndArgsCaller { ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>(); ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>(); FileDescriptor[] fdArray = new FileDescriptor[4]; fds.add(sServerSocket.getFileDescriptor()); peers.add(null); int loopCount = GC_LOOP_COUNT; while (true) { int index; if (loopCount <= 0) { gc();//在比较空闲的时候执行gc loopCount = GC_LOOP_COUNT; } else { loopCount--; } try { fdArray = fds.toArray(fdArray); //这是一个Native方法,其方法内部调用了Select系统函数等待客户端连接请求 index = selectReadable(fdArray);//注意这里的返回值和select()的返回值是不//同的概念,这里Index是活动fd的索引 } catch (IOException ex) { throw new RuntimeException("Error in select()", ex); } if (index < 0) { throw new RuntimeException("Error in select()"); } else if (index == 0) {//有连接进入,放入监听fd队列 ZygoteConnection newPeer = acceptCommandPeer(abiList); peers.add(newPeer); fds.add(newPeer.getFileDescriptor()); } else {//有请求 boolean done; done = peers.get(index).runOnce();//处理请求 if (done) { peers.remove(index); fds.remove(index); } } } } |
boolean runOnce() throws ZygoteInit.MethodAndArgsCaller { String args[]; Arguments parsedArgs = null; FileDescriptor[] descriptors; long startTime = SystemClock.elapsedRealtime(); try { args = readArgumentList();//读取传递进来的请求参数 descriptors = mSocket.getAncillaryFileDescriptors(); }…… ……//fork出应用进程 pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo, parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet, parsedArgs.appDataDir); …… try { if (pid == 0) { // 子进程中 IoUtils.closeQuietly(serverPipeFd); serverPipeFd = null; handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr); return true; } else { // 父进程中 IoUtils.closeQuietly(childPipeFd); childPipeFd = null; //发送pid和usingWrapper给AMS return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs); } } finally { IoUtils.closeQuietly(childPipeFd); IoUtils.closeQuietly(serverPipeFd); } } |
private void handleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr) throws ZygoteInit.MethodAndArgsCaller { closeSocket(); ZygoteInit.closeServerSocket(); …… if (parsedArgs.niceName != null) {//设置进程名字 Process.setArgV0(parsedArgs.niceName); } //参数中配置了RuntimeInit,这里为true if (parsedArgs.runtimeInit) { if (parsedArgs.invokeWith != null) {//Android中另一种可能的启动方式 WrapperInit.execApplication(parsedArgs.invokeWith, parsedArgs.niceName, parsedArgs.targetSdkVersion, pipeFd, parsedArgs.remainingArgs); } else {//程序最终会走到这里 RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, null); } } else { …… } } |
3 分析与总结
原文地址: http://blog.csdn.net/a34140974/article/details/49783781
Android5.0源码分析—— Zygote进程分析相关推荐
- Android6.0源码分析—— Zygote进程分析(补充)
原文地址: http://blog.csdn.net/a34140974/article/details/50915307 此博文为<Android5.0源码分析-- Zygote进程分析> ...
- Android4.0源码Launcher启动流程分析【android源码Launcher系列一】
最近研究ICS4.0的Launcher,发现4.0和2.3有稍微点区别,但是区别不是特别大,所以我就先整理一下Launcher启动的大致流程. Launcher其实是贯彻于手机的整个系统的,时时刻刻都 ...
- Android中ICS4.0源码Launcher启动流程分析【android源码Launcher系列一】
最近研究ICS4.0的Launcher,发现4.0和2.3有稍微点区别,但是区别不是特别大,所以我就先整理一下Launcher启动的大致流程.Launcher其实是贯彻于手机的整个系统的,时时刻刻都在 ...
- android5.0源码开发之NVRam存储,恢复出厂设置数据不被擦除--上篇
MTK有一个特殊的存储区域,叫NVRam,这部分存储器用来保存重要的数据,如:校准参数.IMEI写号.FactoryMode等,即使刷机,只要不格式化下载,这些数据还在,恢复出厂设置也不会被擦除.今天 ...
- Android 7.0 源码分析项目一期竣工啦
从 Android 入行开始,因为工作需求和解决疑难bug的原因陆陆续续的看过一些源码,但都不成系统,从2016年年底开始,在Github上建了一个Android Open Source Projec ...
- android6.0源码分析之Zygote进程分析
在android6.0源码分析之Runtime的初始化一文中,对Zygote进程的初期的Runtime初始化过程进行了分析,在Runtime启动结束后,会对Zygote进程进行初始化,其它Java进程 ...
- 第一次作业:对于Linux2.6.0源码中进程模型的分析
摘要: 作为第一次写博客,可能在排版,页面布局等方面会有大大小小的失误和不足,希望阅读者可以指出,笔者会继续学习,锻炼自己的博客水平:作为第一次分析Linux操作系统,基于进程模型的理解,在不是很熟悉 ...
- android6.0源码分析之Activity启动过程
Activity最为Android开发者最熟悉的组件,由ActivityManagerService服务进行调度管理,而ActivityManagerService的启动过程在activitymana ...
- android6.0源码分析之AMS服务源码分析
activitymanagerservice服务源码分析 1.ActivityManagerService概述 ActivityManagerService(以下简称AMS)作为Android中最核心 ...
最新文章
- Swift中空合运算符、闭区间运算符、单侧区间、半开区间
- 长沙网络推广教你如何在网站优化中让URL标准化?
- LeetCode 213. 打家劫舍 II
- 回溯法(其实是递归)
- 问题步骤记录器——“懒教师”的好帮手
- python 合并word文件,在Python上的WordCloud中,我想合并两种语言
- 前端学习(2462):打包优化
- python获取mac窗口程序内容_在Mac OS X中获取当前活动窗口/文档的标题
- Java中的抽象类和接口(interface),abstract关键字的用法
- 批量修改Dell服务器远程管理卡iDRAC密码
- Maven学习总结(58)—— 常用的 Maven 镜像地址和中央仓库地址汇总
- Cygwin下cscope的配置
- r710 linux网卡驱动,Dell R710更换网卡驱动linux
- java 从socket读数据,从数据读取TcpClient不如socket
- 27岁,大专学历,女程序员内心的感受和行业焦虑
- pathrewrite不生效_webpack配置proxyTable时pathRewrite无效的解决方法
- 防火墙阻止tftp_H3C防火墙常见问题汇总
- ocr文字识别技术有什么意义
- 史上最猛“员工”,疯狂吐槽亿万富翁老板小扎:那么有钱,还总穿着同样的衣服!
- 矩阵乘法 基础训练-蓝桥杯