Zygote

接收客户端创建进程的请求,使用JNI调用linux fork函数创建进程。

Zygote是在Init进程中作为Service被启动的。Zygote进程的主体是:ZygoteInit。

Zygote进程的启动可以参考前篇:Android系统启动过程

    http://www.cnblogs.com/bastard/archive/2012/08/28/2660389.html

系统启动过程如下图:

  

下面主要看看Zygote是如何进行工作的。

一 Zygote工作流程

主函数:

public static void main(String argv[]) {……// Registers a server socket for zygote command connectionsregisterZygoteSocket();/*** Runs the zygote process's select loop. Accepts new connections as* they happen, and reads commands from connections one spawn-request's* worth at a time.*/runSelectLoopMode();    //loop中
}

消息循环是runSelectLoopMode

private static void runSelectLoopMode() throws MethodAndArgsCaller {    … …while (true) {int index;//异步方式 获取ZygoteConnection Command
fdArray = fds.toArray(fdArray);index = selectReadable(fdArray);if(index == 0) {//读取新的ZygoteConnection SocketZygoteConnection newPeer = acceptCommandPeer();peers.add(newPeer);fds.add(newPeer.getFileDesciptor());} else {//处理ZygoteConnection Commandboolean done;done = peers.get(index).runOnce();}     }
}

过程如下图所示:

    

1 ZygoteConnection Command 接收

在ZygoteInit的 main函数中

public static void main(String argv[]) {……// Registers a server socket for zygote command connectionsregisterZygoteSocket();/*** Runs the zygote process's select loop. Accepts new connections as* they happen, and reads commands from connections one spawn-request's* worth at a time.*/runSelectLoopMode();    //loop中
}//registerZygoteSocket注册了Server 端Socket监听ZygoteConnection:private static void registerZygoteSocket() {//” ANDROID_SOCKET_zygote”String env = System.getenv(ANDROID_SOCKET_ENV);fileDesc = Integer.parseInt(env);//private static LocalServerSocket sServerSocket;if (sServerSocket == null) {sServerSocket = new LocalServerSocket(createFileDescriptor(fileDesc));}
}

  使用到了LocalServerSocket进行通信,具体如何进行请看源码。

2 ZygoteConnection Command处理

  在循环中done = peers.get(index).runOnce();——> ZygoteConnection runOnce

       

boolean runOnce( ) {Arguments parsedArgs = null;FileDescriptor[] descriptors;//Reads one start command from the command socket.args = readArgumentList();descriptors = mSocket.getAncillaryFileDescriptors();//创建/Forks a new VM instance /process.//使用Jni 调用nativeForkpid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid,parsedArgs.gids, parsedArgs.debugFlags, rlimits);//返回两次if (pid == 0) {// in child    serverPipeFd = null;handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);// should never get here, the child is expected to eitherreturn true;} else {// in parent...pid of < 0 means failurechildPipeFd = null;return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);}
}

3 Zygote创建新进程的执行

从上面的代码中可以看到创建进程之后返回:

子进程:handleChildProc

父进程:handleParentProc

我们关心的是子进程的执行,继续到handleChildProc中。

// Handles post-fork setup of child proc
private void handleChildProc(Arguments parsedArgs,...){……if (parsedArgs.runtimeInit) {if (parsedArgs.invokeWith != null) {
        //通过系统调用执行进程WrapperInit.execApplication(parsedArgs.invokeWith,parsedArgs.niceName, parsedArgs.targetSdkVersion,pipeFd, parsedArgs.remainingArgs);} else {//通过寻找到相应目标类的main()函数并执行RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,parsedArgs.remainingArgs);}}……
}

看到子进程的执行有两种方式:

  WrapperInit.execApplication和RuntimeInit.zygoteInit

1)通过系统调用的方式执行进程 WrapperInit.execApplication

public static void execApplication(……) {……Zygote.execShell(command.toString());
}public static void execShell(String command) {// using the exec() system callnativeExecShell(command);
}

2)通过寻找到相应目标类的main()函数并执行 RuntimeInit.zygoteInit:

// The main function called when started through the zygote process.
public static final void zygoteInit( ){zygoteInitNative();applicationInit(targetSdkVersion, argv);
}private static void applicationInit( ) {// Remaining arguments are passed to the start class's static maininvokeStaticMain(args.startClass, args.startArgs);
}通过RuntimeInit调用startClass的main函数。

  为何两种方式?可以参考下面文章:

http://blog.csdn.net/21cnbao/article/details/7791254

  以上是Zygote大概简要的工作流程,要深入了解进程创建过程还不行,以上两种方式执行新创建的进程有何区别,

还得熟悉Android,Linux 及其Fork的一些知识和原理。

  linux fork可以参考我转载的文章:

http://www.cnblogs.com/bastard/archive/2012/08/31/2664896.html

  了解了Zygote大概工作流程,如果我们要创建进程该如何告知Zygote呢?

在StartActivity如果是启动新的应用就会创建该应用的进程,下面我们可以看一下StartActivity时创建进程的过程。

二 应用程序进程的创建过程

启动一个新的应用程序为例,启动新的应用程序时候是以startActivity的方式进行,这个过程大致如下图:

    

  在启动应用程序的时需要创建应用程序的进程,执行到:

  ActivityManagerService的startProcessLocked函数中;看一下这个函数过程:

private final void startProcessLocked(ProcessRecord app,String hostingType, String hostingNameStr)
{// Start the process.  It will either succeed and return a result containing// the PID of the new process, or else throw a RuntimeException.Process.ProcessStartResult startResult =Process.start("android.app.ActivityThread",app.processName, uid, uid, gids, debugFlags,app.info.targetSdkVersion, zygoteArgs);
}

  到了Process这个类:Tools for managing OS processes.

public static final ProcessStartResult start(…… ) {return startViaZygote(processClass, niceName, uid, gid, gids,debugFlags, targetSdkVersion, zygoteArgs);
}//Starts a new process via the zygote mechanism.
private static ProcessStartResult startViaZygote(…… )
{synchronized(Process.class) {ArrayList<String> argsForZygote = new ArrayList<String>();//参数设置// --runtime-init, --setuid=, --setgid=,……//--runtime-init这里决定上面所提到创建新的进程的启动方式argsForZygote.add("--runtime-init");         argsForZygote.add("--setuid=" + uid);argsForZygote.add("--setgid=" + gid);//……argsForZygote.add(processClass);for (String arg : extraArgs) {argsForZygote.add(arg);}   return zygoteSendArgsAndGetResult(argsForZygote);}}

//Sends an argument list to the zygote process, which starts a new child
//and returns the child's pid
private static ProcessStartResult zygoteSendArgsAndGetResult(ArrayList<String> args)
{//open socket to Zygote process if not already openopenZygoteSocketIfNeeded();//write ArgumentsZygoteWriter.write(Integer.toString(args.size()));sZygoteWriter.newLine();sZygoteWriter.flush();……}

  通过上面这一段代码,向Zygote发送创建进程的请求,设置相关的参数。

其中有argsForZygote.add("--runtime-init");    决定新创建进程的启动方式为RuntimeInit.zygoteInit方式启动:

找到目标类main函数执行。

  processClass"android.app.ActivityThread",将是进程创建之后执行的类,执行其中的main函数。

联系上面的流程:

  即创建进程后执行到RuntimeInit.zygoteInit:(直接找到目标类的main函数调用不是系统调用)

// The main function called when started through the zygote process.
public static final void zygoteInit( ){applicationInit(targetSdkVersion, argv);
}private static void applicationInit( ) {
    //后将执行:ActivityThread的main函数,启动界面。invokeStaticMain(args.startClass, args.startArgs);}

ActivityThread就是应用程序的主线程的入口。

  以上便是Zygote工作流程和启动应用程序创建进程大概简单过程,其中所涉及到知识和框架比较多,还需要去理解linux fork知识和原理,

进程概念,Android进程通信机制Binder,Activity启动过程等。这里仅简单的从代码上做流程分析。

  参考文档:

http://blog.csdn.net/luoshengyang/article/details/6689748

Zygote工作流程分析相关推荐

  1. Framework原理分析之——Zygote进程流程分析

    在启动Zygote进程的分析中,我们知道其实是通过系统调用fork()函数来创建一个进程,然后执行Zygote.rc中的执行文件,从而开始Zygote进程业务. 本篇文章我们就来分析大名鼎鼎的Zygo ...

  2. 16.U-boot的工作流程分析-2440

    16.U-boot的工作流程分析-2440 分析的流程: 程序入口 第一阶段程序分析 第二阶段程序分析 2440开发板: 1.uboot的入口: 要看uboot工程的入口,首先打开顶层目录的Makef ...

  3. K8S架构设计及工作流程分析

    Kubernetes架构设计 核心组件 api server 功能 controller manager 负责维护集群的状态 scheduler 负责资源的调度按照预定的调度策略将Pod调度到相应的机 ...

  4. kafka的基本概念和工作流程分析

    为什么需要消息队列 周末无聊刷着手机,某宝网APP突然蹦出来一条消息"为了回馈老客户,女朋友买一送一,活动仅限今天!".买一送一还有这种好事,那我可不能错过!忍不住立马点了去.于是 ...

  5. 【转载】csr8670--sink工程的大致工作流程分析(以speaker为例)二

    csr8670--sink工程的大致工作流程分析(以speaker为例)二 1.编解码任务的初始化 继续接着流程一分析: 1.1 当连接初始化完成之后,如下所示会调用编解码的初始化任务:这个编解码的任 ...

  6. 【SemiDrive源码分析】【X9芯片启动流程】14 - freertos_safetyos目录Cortex-R5 SafetyOS/RTOS工作流程分析

    [SemiDrive源码分析][X9芯片启动流程]14 - freertos_safetyos目录Cortex-R5 SafetyOS/RTOS工作流程分析 一.SafetyOS 工作流程分析 1. ...

  7. 你想要的系列:网络请求框架OkHttp3全解系列 - (二)OkHttp的工作流程分析

    Okhttp系列文章: 你想要的系列:网络请求框架OkHttp3全解系列 - (一)OkHttp的基本使用 你想要的系列:网络请求框架OkHttp3全解系列 - (二)OkHttp的工作流程分析 你想 ...

  8. Android 7.0 WifiMonitor工作流程分析

    2019独角兽企业重金招聘Python工程师标准>>> 在wifi启动扫描的分析过程中,出现了多次WifiMonitor的操作,在此分析一下这个函数是如何工作的. 在Android的 ...

  9. NSURLSession使用说明及后台工作流程分析

    NSURLSession简介 NSURLSession是iOS7中新的网络接口,它与咱们熟悉的NSURLConnection是并列的.在程序在前台时,NSURLSession与NSURLConnect ...

最新文章

  1. 【Java】基本二叉搜索树讲解
  2. try()...catch()的用法
  3. NR 5G 身份标识
  4. 将VMware Workstation 12 Pro的虚拟网卡修改为自己希望的IP网段
  5. 掌握这 20 个容器实战技巧!
  6. AI繁荣下的隐忧——Google Tensorflow安全风险剖析
  7. JVM调优总结(四)-垃圾回收面临的问题
  8. 如何在SAP CRM Fiori My Task应用里创建task
  9. 哪种语言 连接 oracle,Go语言连接Oracle(就我这个最全)
  10. [jQuery基础] jQuery对象 -- 属性操作
  11. html搜题软件,大学搜题app哪个好_大学好的搜题软件_大学搜题免费
  12. Xcode CoreData 存储报错问题。
  13. rarlinux基于linux-x64
  14. 课程设计(银行叫号机系统)
  15. Ice通信之Ice::Application
  16. 开关电源EMI整改实例(方法)。
  17. 基于SpringBoot的网上电影票购买系统设计与实现
  18. 鸡与 兔有几条腿的问题
  19. 计量经济学笔记3-Eviews操作-多元线性回归
  20. 揭密巴西Banrisul银行网站遭遇5小时劫持的原因

热门文章

  1. Python之Time模块
  2. 在kubernetes集群中运行nginx
  3. 远程桌面时提示凭证不工作问题的终极解决办法
  4. python对象继承
  5. 《Java程序性能优化》之设计优化
  6. 与众不同 windows phone (29) - Communication(通信)之与 OData 服务通信
  7. Android Prefence 总结
  8. DynamipsGUI2.8 交换模块试用(Etherchannel)
  9. ubuntu的xfce4的display只有一种分辨率选项
  10. Nifi清空Queue操作