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 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:
private static void runSelectLoopMode() 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 Command
boolean done; done = peers.get(index).runOnce(); } } }
過程如下圖所示:
1 ZygoteConnection Command 接收
在ZygoteInit的 main函數中
public static void 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:
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 調用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 either
return true; } 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 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 call nativeExecShell(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 main invokeStaticMain(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 open openZygoteSocketIfNeeded(); //write Argument sZygoteWriter.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啟動過程等。這里僅簡單的從代碼上做流程分析。
參考文檔: