Android6.0的应用进程启动过程部分分析
2017-06-09 14:42
387 查看
本文主要参考:http://blog.csdn.net/threepigs/article/details/50779056 深入理解Dalvik虚拟机- Android应用进程启动过程分析 一文,改成Android6.0的对应代码和启动过程。
Android的应用进程启动是apk在manifest里申明的Activity,Service,BroadcastReceiver等组件被调起时而触发的。我们以Activity为例,当点击桌面上的应用图标时,桌面会调用startActivity,启动manifest里申明的相应Launcher的Activity,而Activity的startActivity会通过Binder调用来到ActivityManagerService(AMS)里。AMS是system_server的一个服务,负责管理Android系统的所有Activity的栈,逻辑比较复杂。AMS里startActivity的时候,如果发现这个应用进程没有启动,那么就会通过Zygote创建出这个进程。
通过调用Process.start来启动进程,”android.app.ActivityThread” 这个参数是整个进程启动的入口类,后续的分析可以看到,进程被fork出来之后,就会调用android.app.ActivityThread的main函数。
调用startViaZygote函数,从代码可以看到,Zygote创建进程是socket跨进程的调用。通过LocalSocket通信,来完成进程的创建,所以这里的Process.start只是一个Client端的调用,实际是由Server端的接收到消息后处理的。
Server端是app_process这个进程里,这是个常驻的系统服务。
frameworks/base/cmds/app_process/app_main.cpp
AppRuntime继承自AndroidRuntime,AndroidRuntime类是libandroid_runtime.so里导出的,frameworks/base/core/jni/AndroidRuntime.cpp。
app_ process这个进程在init.rc里会创建,app_process以zygote作为进程名。
第一个if是正常的Zygote进程启动,执行AndroidRuntime::start,会调用ZygoteInit的类main函数。app_process的初始化就在ZygoteInit里,监听本地的socket,接收ZygoteClient的请求,当有请求来的时候,调用ZygoteConnection::runOnce,从而调用Zygote.forkAndSpecialize来创建新的进程,并且调用RuntimeInit.zygoteInit做进程的初始化,初始化过程就会调用ActivityThread.main。
第二个当指定了className的时候,则用com.android.internal.os.RuntimeInit作为入口。
而我们正常的Zygote进程则走的是ZygoteInit。
AndroidRuntime.start函数会调用startVm,frameworks/base/core/jni/AndroidRuntime.cpp。
而start函数中的CallStaticVoidMethod函数开始执行找到的类方法。
Android的应用进程启动是apk在manifest里申明的Activity,Service,BroadcastReceiver等组件被调起时而触发的。我们以Activity为例,当点击桌面上的应用图标时,桌面会调用startActivity,启动manifest里申明的相应Launcher的Activity,而Activity的startActivity会通过Binder调用来到ActivityManagerService(AMS)里。AMS是system_server的一个服务,负责管理Android系统的所有Activity的栈,逻辑比较复杂。AMS里startActivity的时候,如果发现这个应用进程没有启动,那么就会通过Zygote创建出这个进程。
//frameworks/base/services/Java/com/android/server/am/ActivityManagerService.java 3253 private final void startProcessLocked(ProcessRecord app, String hostingType, 3254 String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) { ... 3376 // Start the process. It will either succeed and return a result containing 3377 // the PID of the new process, or else throw a RuntimeException. 3378 boolean isActivityProcess = (entryPoint == null); 3379 if (entryPoint == null) entryPoint = "android.app.ActivityThread"; 3380 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " + 3381 app.processName); 3382 checkTime(startTime, "startProcess: asking zygote to start proc"); 3383 Process.ProcessStartResult startResult = Process.start(entryPoint, 3384 app.processName, uid, uid, gids, debugFlags, mountExternal, 3385 app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet, 3386 app.info.dataDir, entryPointArgs); ... 3451 }
通过调用Process.start来启动进程,”android.app.ActivityThread” 这个参数是整个进程启动的入口类,后续的分析可以看到,进程被fork出来之后,就会调用android.app.ActivityThread的main函数。
//~/android-6.0.1_r62/frameworks/base/core/java/android/os/Process.java 447 /** 448 * Start a new process. 449 * 450 * <p>If processes are enabled, a new process is created and the 451 * static main() function of a <var>processClass</var> is executed there. 452 * The process will continue running after this function returns. 453 * 454 * <p>If processes are not enabled, a new thread in the caller's 455 * process is created and main() of <var>processClass</var> called there. 456 * 457 * <p>The niceName parameter, if not an empty string, is a custom name to 458 * give to the process instead of using processClass. This allows you to 459 * make easily identifyable processes even if you are using the same base 460 * <var>processClass</var> to start them. 461 * 462 * @param processClass The class to use as the process's main entry 463 * point. 464 * @param niceName A more readable name to use for the process. 465 * @param uid The user-id under which the process will run. 466 * @param gid The group-id under which the process will run. 467 * @param gids Additional group-ids associated with the process. 468 * @param debugFlags Additional flags. 469 * @param targetSdkVersion The target SDK version for the app. 470 * @param seInfo null-ok SELinux information for the new process. 471 * @param abi non-null the ABI this app should be started with. 472 * @param instructionSet null-ok the instruction set to use. 473 * @param appDataDir null-ok the data directory of the app. 474 * @param zygoteArgs Additional arguments to supply to the zygote process. 475 * 476 * @return An object that describes the result of the attempt to start the process. 477 * @throws RuntimeException on fatal start failure 478 * 479 * {@hide} 480 */ 481 public static final ProcessStartResult start(final String processClass, 482 final String niceName, 483 int uid, int gid, int[] gids, 484 int debugFlags, int mountExternal, 485 int targetSdkVersion, 486 String seInfo, 487 String abi, 488 String instructionSet, 489 String appDataDir, 490 String[] zygoteArgs) { ... 491 try { 492 return startViaZygote(processClass, niceName, uid, gid, gids, 493 debugFlags, mountExternal, targetSdkVersion, seInfo, 494 abi, instructionSet, appDataDir, zygoteArgs); 495 } catch (ZygoteStartFailedEx ex) { 496 Log.e(LOG_TAG, 497 "Starting VM process through Zygote failed"); 498 throw new RuntimeException( 499 "Starting VM process through Zygote failed", ex); 500 } 501 } 584 /** 585 * Starts a new process via the zygote mechanism. 586 * 587 * @param processClass Class name whose static main() to run 588 * @param niceName 'nice' process name to appear in ps 589 * @param uid a POSIX uid that the new process should setuid() to 590 * @param gid a POSIX gid that the new process shuold setgid() to 591 * @param gids null-ok; a list of supplementary group IDs that the 592 * new 4000 process should setgroup() to. 593 * @param debugFlags Additional flags. 594 * @param targetSdkVersion The target SDK version for the app. 595 * @param seInfo null-ok SELinux information for the new process. 596 * @param abi the ABI the process should use. 597 * @param instructionSet null-ok the instruction set to use. 598 * @param appDataDir null-ok the data directory of the app. 599 * @param extraArgs Additional arguments to supply to the zygote process. 600 * @return An object that describes the result of the attempt to start the process. 601 * @throws ZygoteStartFailedEx if process start failed for any reason 602 */ 603 private static ProcessStartResult startViaZygote(final String processClass, 604 final String niceName, 605 final int uid, final int gid, 606 final int[] gids, 607 int debugFlags, int mountExternal, 608 int targetSdkVersion, 609 String seInfo, 610 String abi, 611 String instructionSet, 612 String appDataDir, 613 String[] extraArgs) 614 throws ZygoteStartFailedEx { ... 696 return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote); 697 } 698 } 714 /** 715 * Tries to open socket to Zygote process if not already open. If 716 * already open, does nothing. May block and retry. 717 */ 718 private static ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx { 719 if (primaryZygoteState == null || primaryZygoteState.isClosed()) { 720 try { 721 primaryZygoteState = ZygoteState.connect(ZYGOTE_SOCKET); 722 } catch (IOException ioe) { 723 throw new ZygoteStartFailedEx("Error connecting to primary zygote", ioe); 724 } 725 } 726 727 if (primaryZygoteState.matches(abi)) { 728 return primaryZygoteState; 729 } 730 731 // The primary zygote didn't match. Try the secondary. 732 if (secondaryZygoteState == null || secondaryZygoteState.isClosed()) { 733 try { 734 secondaryZygoteState = ZygoteState.connect(SECONDARY_ZYGOTE_SOCKET); 735 } catch (IOException ioe) { 736 throw new ZygoteStartFailedEx("Error connecting to secondary zygote", ioe); 737 } 738 } 739 740 if (secondaryZygoteState.matches(abi)) { 741 return secondaryZygoteState; 742 } 743 744 throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi); 745 } 437 /** 438 * The state of the connection to the primary zygote. 439 */ 440 static ZygoteState primaryZygoteState; 441 442 /** 443 * The state of the connection to the secondary zygote. 444 */ 445 static ZygoteState secondaryZygoteState;
调用startViaZygote函数,从代码可以看到,Zygote创建进程是socket跨进程的调用。通过LocalSocket通信,来完成进程的创建,所以这里的Process.start只是一个Client端的调用,实际是由Server端的接收到消息后处理的。
Server端是app_process这个进程里,这是个常驻的系统服务。
frameworks/base/cmds/app_process/app_main.cpp
34 class AppRuntime : public AndroidRuntime 35 { ... 112 };
AppRuntime继承自AndroidRuntime,AndroidRuntime类是libandroid_runtime.so里导出的,frameworks/base/core/jni/AndroidRuntime.cpp。
app_ process这个进程在init.rc里会创建,app_process以zygote作为进程名。
//~/android-6.0.1_r62/frameworks/base/cmds/app_process/app_main.cpp 186 int main(int argc, char* const argv[]) 187 { ... 197 AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv)); 198 // Process command line arguments 199 // ignore argv[0] 200 argc--; 201 argv++; ... 306 if (zygote) { 307 runtime.start("com.android.internal.os.ZygoteInit", args, zygote); 308 } else if (className) { 309 runtime.start("com.android.internal.os.RuntimeInit", args, zygote); 310 } else { 311 fprintf(stderr, "Error: no class name or --zygote supplied.\n"); 312 app_usage(); 313 LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied."); 314 return 10; 315 } 316 }
第一个if是正常的Zygote进程启动,执行AndroidRuntime::start,会调用ZygoteInit的类main函数。app_process的初始化就在ZygoteInit里,监听本地的socket,接收ZygoteClient的请求,当有请求来的时候,调用ZygoteConnection::runOnce,从而调用Zygote.forkAndSpecialize来创建新的进程,并且调用RuntimeInit.zygoteInit做进程的初始化,初始化过程就会调用ActivityThread.main。
//~/android-6.0.1_r62/frameworks/base/core/jni/AndroidRuntime.cpp 999 /* 1000 * Start the Android runtime. This involves starting the virtual machine 1001 * and calling the "static void main(String[] args)" method in the class 1002 * named by "className". 1003 * 1004 * Passes the main function two arguments, the class name and the specified 1005 * options string. 1006 */ 1007 void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote) 1008 { ... 1036 //const char* kernelHack = getenv("LD_ASSUME_KERNEL"); 1037 //ALOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack); 1038 1039 /* start the virtual machine */ 1040 JniInvocation jni_invocation; 1041 jni_invocation.Init(NULL); 1042 JNIEnv* env; 1043 if (startVm(&mJavaVM, &env, zygote) != 0) { 1044 return; 1045 } 1046 onVmCreated(env); ... 1079 /* 1080 * Start VM. This thread becomes the main thread of the VM, and will 1081 * not return until the VM exits. 1082 */ 1083 char* slashClassName = toSlashClassName(className); 1084 jclass startClass = env->FindClass(slashClassName); 1085 if (startClass == NULL) { 1086 ALOGE("JavaVM unable to locate class '%s'\n", slashClassName); 1087 /* keep going */ 1088 } else { 1089 jmethodID startMeth = env->GetStaticMethodID(startClass, "main", 1090 "([Ljava/lang/String;)V"); 1091 if (startMeth == NULL) { 1092 ALOGE("JavaVM unable to find main() in '%s'\n", className); 1093 /* keep going */ 1094 } else { 1095 env->CallStaticVoidMethod(startClass, startMeth, strArray);//执行类方法 1096 1097 #if 0 1098 if (env->ExceptionCheck()) 1099 threadExitUncaughtException(env); 1100 #endif 1101 } 1102 } 1103 free(slashClassName); ... 1110 }
第二个当指定了className的时候,则用com.android.internal.os.RuntimeInit作为入口。
而我们正常的Zygote进程则走的是ZygoteInit。
AndroidRuntime.start函数会调用startVm,frameworks/base/core/jni/AndroidRuntime.cpp。
而start函数中的CallStaticVoidMethod函数开始执行找到的类方法。
相关文章推荐
- 源码分析Android 应用进程的启动过程
- Android 8.0系统源码分析--应用进程启动过程分析
- Android6.0 WMS(五) WMS计算Activity窗口大小的过程分析(一)应用进程
- Android6.0的phone应用源码分析(2)——phone相关进程启动分析
- 分析Android 根文件系统启动过程(init守护进程分析)
- 分析Android 根文件系统启动过程(init守护进程分析)
- 分析Android 根文件系统启动过程(init守护进程分析)
- Android应用程序在新的进程中启动新的Activity的方法和过程分析
- [zz] 分析Android 根文件系统启动过程(init守护进程分析)
- 分析Android 根文件系统启动过程(init守护进程分析)
- Android 根文件系统启动过程(init进程 详细分析)
- 项目清单文件分析与第一个ANDROID应用的启动过程
- Android系统在新进程中启动自定义服务过程(startService)的原理分析
- 分析Android 根文件系统启动过程(init守护进程分析)
- Busybox init进程启动过程分析
- 分析Android 根文件系统启动过程(init守护进程分析)
- 分析Android 根文件系统启动过程(init守护进程分析)
- 分析Android 根文件系统启动过程(init守护进程分析)
- 分析Android 根文件系统启动过程(init守护进程分析)
- Android系统在新进程中启动自定义服务过程(startService)的原理分析