Zygoteワークフロー分析

14605 ワード

Zygoteワークフロー分析
Zygote
クライアント作成プロセスの要求を受信し、JNIを使用してlinux fork関数を呼び出してプロセスを作成します.
ZygoteはInitプロセスでサービスとして起動されます.Zygoteプロセスの主体は,ZygoteInitである.
Zygoteプロセスの起動は前編:Androidシステムの起動プロセスを参考にすることができます
http://www.cnblogs.com/bastard/archive/2012/08/28/2660389.html
システム起動プロセスは以下の図の通りです.

次は主にZygoteがどのように仕事をしているかを見てみましょう.
Zygoteワークフロー
主関数:
publicstaticvoid main(String argv[]) {       ……       // Registers a server socket for zygote command connections    registerZygoteSocket();        /**       * 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です.
privatestaticvoidrunSelectLoopMode() throws MethodAndArgsCaller {
    … …       while(true) {              int index;              // ZygoteConnection Command              fdArray = fds.toArray(fdArray);              index = selectReadable(fdArray);
if(index == 0) {                     // ZygoteConnection Socket                     ZygoteConnection newPeer = acceptCommandPeer();                     peers.add(newPeer);                     fds.add(newPeer.getFileDesciptor());              } else {                     // ZygoteConnection Commandboolean done;                     done = peers.get(index).runOnce();                    }            }}


手順は次の図のとおりです.

1 ZygoteConnection Command受信
ZygoteInitのmain関数で
publicstaticvoid main(String argv[]) {    ……    // Registers a server socket for zygote command connections  registerZygoteSocket();    /**    * 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:
privatestaticvoid 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   nativeFork       pid = 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 eitherreturntrue;       } else {              // in parent...pid of < 0 means failure              childPipeFd = null;              return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);       }}


3 Zygote新規作成プロセスの実行
上記のコードから、作成プロセスの後に戻ることがわかります.
サブプロセス:handleChildProc
親プロセス:handleParentProc
私たちが関心を持っているのは、handleChildProcに進むサブプロセスの実行です.
// Handles post-fork setup of child procprivatevoid 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);           }       }       ……}


サブプロセスの実行には2つの方法があります.
  WrapperInit.义齿zygoteInit:
1)システム呼び出しによりプロセスWrapperInitを実行する.execApplication:
publicstaticvoid execApplication(……) {  ……  Zygote.execShell(command.toString());}publicstaticvoid execShell(String command) {  // using the exec() system callnativeExecShell(command);}


2)該当ターゲットクラスのmain()関数を探してRuntimeInitを実行する.zygoteInit:
// The main function called when started through the zygote process.publicstaticfinalvoid zygoteInit( ){        zygoteInitNative();        applicationInit(targetSdkVersion, argv);}privatestaticvoid applicationInit( ) {        // Remaining arguments are passed to the start class's static main        invokeStaticMain(args.startClass, args.startArgs);}
RuntimeInit startClass main 。


なぜ2つの方法がありますか?次の文書を参照してください.
http://blog.csdn.net/21cnbao/article/details/7791254
以上はZygoteの簡単なワークフローですが、プロセスの作成プロセスがまだだめであることを深く理解するには、上記の2つの方法で新しく作成されたプロセスを実行するのにどのような違いがありますか.
Android、Linux、Forkのいくつかの知識と原理を熟知しなければなりません.
linux forkは私が転載した文章を参考にすることができます.
http://www.cnblogs.com/bastard/archive/2012/08/31/2664896.html
Zygoteのおおよそのワークフローを理解しましたが、プロセスを作成するにはどのようにZygoteに伝えますか?
StartActivityで新しいアプリケーションを起動するとそのアプリケーションのプロセスが作成されます.次に、StartActivityでプロセスを作成するプロセスを見てみましょう.
二アプリケーションプロセスの作成プロセス
新しいアプリケーションを起動する例として、新しいアプリケーションを起動するときはstartActivityで行います.このプロセスは大体次の図になります.

アプリケーションを開始するときにアプリケーションを作成する必要があるプロセスは、次のように実行されます.
ActivityManagerServiceのstartProcessLocked関数この関数の手順を見てみましょう.
privatefinalvoid 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);}


プロセスというクラスに着きました:Tools for managing OS process.
publicstaticfinal ProcessStartResult start(…… ) {       return startViaZygote(processClass, niceName, uid, gid, gids,                    debugFlags, targetSdkVersion, zygoteArgs);}//Starts a new process via the zygote mechanism.privatestatic 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 pidprivatestatic ProcessStartResult zygoteSendArgsAndGetResult    (ArrayList<String> args){       //open socket to Zygote process if not already open       openZygoteSocketIfNeeded();       //write Argument       sZygoteWriter.write(Integer.toString(args.size()));       sZygoteWriter.newLine();       sZygoteWriter.flush();       ……}


上記のコードで、作成プロセスの要求をZygoteに送信し、関連するパラメータを設定します.
中にはargsForZygote.add("--runtime-init"); 新規作成プロセスの開始方法をRuntimeInitと決定する.zygoteInit方式起動:
ターゲットクラスmain関数の実行を見つけます.
プロセスクラスは「android.app.Activity Thread」であり、プロセス作成後に実行されるクラスであり、main関数を実行します.
上記の手順に連絡します.
プロセスの作成後にRuntimeInitに実行する.zygoteInit:(ターゲットクラスを直接見つけたmain関数呼び出しはシステム呼び出しではありません)
// The main function called when started through the zygote process.publicstaticfinalvoid zygoteInit( ){        applicationInit(targetSdkVersion, argv);}privatestaticvoid applicationInit( ) {//    :ActivityThread main  ,    。       invokeStaticMain(args.startClass, args.startArgs);}


Activity Threadはアプリケーションのメインスレッドのエントリです.
以上、Zygoteワークフローとアプリケーション作成プロセスの起動は簡単ですが、知識とフレームワークが多く、linux forkの知識と原理を理解する必要があります.
プロセスコンセプト、Androidプロセス通信メカニズムBinder、Activity起動プロセスなど.ここではコードからプロセス分析を簡単に行うだけです.
参照ドキュメント:
http://blog.csdn.net/luoshengyang/article/details/6689748