Zygote工作流程分析
Zygote
?????? 接收客戶端創(chuàng)建進(jìn)程的請(qǐng)求,使用JNI調(diào)用linux fork函數(shù)創(chuàng)建進(jìn)程。
Zygote是在Init進(jìn)程中作為Service被啟動(dòng)的。Zygote進(jìn)程的主體是:ZygoteInit。
?????? Zygote進(jìn)程的啟動(dòng)可以參考前篇:Android系統(tǒng)啟動(dòng)過程
?http://www.cnblogs.com/bastard/archive/2012/08/28/2660389.html
系統(tǒng)啟動(dòng)過程如下圖:
?
下面主要看看Zygote是如何進(jìn)行工作的。
一 Zygote工作流程
主函數(shù):
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中 }?
?
消息循環(huán)是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函數(shù)中
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注冊(cè)了Server 端Socket監(jiān)聽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進(jìn)行通信,具體如何進(jìn)行請(qǐng)看源碼。
?
2 ZygoteConnection Command處理
在循環(huán)中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();//創(chuàng)建/Forks a new VM instance /process.//使用Jni 調(diào)用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創(chuàng)建新進(jìn)程的執(zhí)行
從上面的代碼中可以看到創(chuàng)建進(jìn)程之后返回:
?????? 子進(jìn)程:handleChildProc
?????? 父進(jìn)程:handleParentProc
我們關(guān)心的是子進(jìn)程的執(zhí)行,繼續(xù)到handleChildProc中。
// Handles post-fork setup of child proc private void handleChildProc(Arguments parsedArgs,...){……if (parsedArgs.runtimeInit) {if (parsedArgs.invokeWith != null) { //通過系統(tǒng)調(diào)用執(zhí)行進(jìn)程WrapperInit.execApplication(parsedArgs.invokeWith,parsedArgs.niceName, parsedArgs.targetSdkVersion,pipeFd, parsedArgs.remainingArgs);} else {//通過尋找到相應(yīng)目標(biāo)類的main()函數(shù)并執(zhí)行RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,parsedArgs.remainingArgs);}}…… }?
看到子進(jìn)程的執(zhí)行有兩種方式:
WrapperInit.execApplication和RuntimeInit.zygoteInit:
1)通過系統(tǒng)調(diào)用的方式執(zhí)行進(jìn)程?WrapperInit.execApplication:
public static void execApplication(……) {……Zygote.execShell(command.toString()); }public static void execShell(String command) {// using the exec() system callnativeExecShell(command); }?
?
2)通過尋找到相應(yīng)目標(biāo)類的main()函數(shù)并執(zhí)行?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調(diào)用startClass的main函數(shù)。
?
為何兩種方式?可以參考下面文章:
?????? http://blog.csdn.net/21cnbao/article/details/7791254
以上是Zygote大概簡(jiǎn)要的工作流程,要深入了解進(jìn)程創(chuàng)建過程還不行,以上兩種方式執(zhí)行新創(chuàng)建的進(jìn)程有何區(qū)別,
還得熟悉Android,Linux 及其Fork的一些知識(shí)和原理。
linux fork可以參考我轉(zhuǎn)載的文章:
?????? http://www.cnblogs.com/bastard/archive/2012/08/31/2664896.html
了解了Zygote大概工作流程,如果我們要?jiǎng)?chuàng)建進(jìn)程該如何告知Zygote呢?
在StartActivity如果是啟動(dòng)新的應(yīng)用就會(huì)創(chuàng)建該應(yīng)用的進(jìn)程,下面我們可以看一下StartActivity時(shí)創(chuàng)建進(jìn)程的過程。
?
二 應(yīng)用程序進(jìn)程的創(chuàng)建過程
?????? 啟動(dòng)一個(gè)新的應(yīng)用程序?yàn)槔?#xff0c;啟動(dòng)新的應(yīng)用程序時(shí)候是以startActivity的方式進(jìn)行,這個(gè)過程大致如下圖:
??????
?
在啟動(dòng)應(yīng)用程序的時(shí)需要?jiǎng)?chuàng)建應(yīng)用程序的進(jìn)程,執(zhí)行到:
ActivityManagerService的startProcessLocked函數(shù)中;看一下這個(gè)函數(shù)過程:
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這個(gè)類: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>();//參數(shù)設(shè)置// --runtime-init, --setuid=, --setgid=,……//--runtime-init這里決定上面所提到創(chuàng)建新的進(jìn)程的啟動(dòng)方式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發(fā)送創(chuàng)建進(jìn)程的請(qǐng)求,設(shè)置相關(guān)的參數(shù)。
其中有argsForZygote.add("--runtime-init");??? 決定新創(chuàng)建進(jìn)程的啟動(dòng)方式為RuntimeInit.zygoteInit方式啟動(dòng):
找到目標(biāo)類main函數(shù)執(zhí)行。
processClass為"android.app.ActivityThread",將是進(jìn)程創(chuàng)建之后執(zhí)行的類,執(zhí)行其中的main函數(shù)。
聯(lián)系上面的流程:
即創(chuàng)建進(jìn)程后執(zhí)行到RuntimeInit.zygoteInit中:(直接找到目標(biāo)類的main函數(shù)調(diào)用不是系統(tǒng)調(diào)用)
// The main function called when started through the zygote process. public static final void zygoteInit( ){applicationInit(targetSdkVersion, argv); }private static void applicationInit( ) { //后將執(zhí)行:ActivityThread的main函數(shù),啟動(dòng)界面。invokeStaticMain(args.startClass, args.startArgs);}?
ActivityThread就是應(yīng)用程序的主線程的入口。
?
以上便是Zygote工作流程和啟動(dòng)應(yīng)用程序創(chuàng)建進(jìn)程大概簡(jiǎn)單過程,其中所涉及到知識(shí)和框架比較多,還需要去理解linux fork知識(shí)和原理,
進(jìn)程概念,Android進(jìn)程通信機(jī)制Binder,Activity啟動(dòng)過程等。這里僅簡(jiǎn)單的從代碼上做流程分析。
參考文檔:
http://blog.csdn.net/luoshengyang/article/details/6689748
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的Zygote工作流程分析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android手机WIFI与电脑间共享文
- 下一篇: 代码添加ProgressBar 进度条