Android6.0的应用进程启动过程部分分析

本文解析了Android应用进程启动过程,从Activity调用startActivity出发,深入到ActivityManagerService内部,直至Zygote进程创建和ActivityThread.main()的执行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文主要参考:http://blog.youkuaiyun.com/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创建出这个进程。

//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 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函数开始执行找到的类方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值