`

Android应用程序进程启动过程的源代码分析

 
阅读更多

Android应用程序框架层创建的应用程序进程具有两个特点,一是进程的入口函数是ActivityThread.main,二是进程天然支持Binder进程间通信机制;这两个特点都是在进程的初始化过程中实现的,本文将详细分析Android应用程序进程创建过程中是如何实现这两个特点的。

Android应用程序框架层创建的应用程序进程的入口函数是ActivityThread.main比较好理解,即进程创建完成之后,Android应用程序框架层就会在这个进程中将ActivityThread类加载进来,然后执行它的main函数,这个main函数就是进程执行消息循环的地方了。Android应用程序框架层创建的应用程序进程天然支持Binder进程间通信机制这个特点应该怎么样理解呢?前面我们在学习Android系统的Binder进程间通信机制时说到,它具有四个组件,分别是驱动程序、守护进程、Client以及Server,其中Server组件在初始化时必须进入一个循环中不断地与Binder驱动程序进行到交互,以便获得Client组件发送的请求,具体可参考Android系统进程间通信(IPC)机制Binder中的Server启动过程源代码分析一文,但是,当我们在Android应用程序中实现Server组件的时候,我们并没有让进程进入一个循环中去等待Client组件的请求,然而,当Client组件得到这个Server组件的远程接口时,却可以顺利地和Server组件进行进程间通信,这就是因为Android应用程序进程在创建的时候就已经启动了一个线程池来支持Server组件和Binder驱动程序之间的交互了,这样,极大地方便了在Android应用程序中创建Server组件。

在Android应用程序框架层中,是由ActivityManagerService组件负责为Android应用程序创建新的进程的,它本来也是运行在一个独立的进程之中,不过这个进程是在系统启动的过程中创建的。ActivityManagerService组件一般会在什么情况下会为应用程序创建一个新的进程呢?当系统决定要在一个新的进程中启动一个Activity或者Service时,它就会创建一个新的进程了,然后在这个新的进程中启动这个Activity或者Service,具体可以参考Android系统在新进程中启动自定义服务过程(startService)的原理分析、Android应用程序启动过程源代码分析和Android应用程序在新的进程中启动新的Activity的方法和过程分析这三篇文章。

ActivityManagerService启动新的进程是从其成员函数startProcessLocked开始的,在深入分析这个过程之前,我们先来看一下进程创建过程的序列图,然后再详细分析每一个步骤。


点击查看大图

Step 1. ActivityManagerService.startProcessLocked

这个函数定义在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:

view plain
  1. publicfinalclassActivityManagerServiceextendsActivityManagerNative
  2. implementsWatchdog.Monitor,BatteryStatsImpl.BatteryCallback{
  3. ......
  4. privatefinalvoidstartProcessLocked(ProcessRecordapp,
  5. StringhostingType,StringhostingNameStr){
  6. ......
  7. try{
  8. intuid=app.info.uid;
  9. int[]gids=null;
  10. try{
  11. gids=mContext.getPackageManager().getPackageGids(
  12. app.info.packageName);
  13. }catch(PackageManager.NameNotFoundExceptione){
  14. ......
  15. }
  16. ......
  17. intdebugFlags=0;
  18. ......
  19. intpid=Process.start("android.app.ActivityThread",
  20. mSimpleProcessManagement?app.processName:null,uid,uid,
  21. gids,debugFlags,null);
  22. ......
  23. }catch(RuntimeExceptione){
  24. ......
  25. }
  26. }
  27. ......
  28. }
它调用了Process.start函数开始为应用程序创建新的进程,注意,它传入一个第一个参数为"android.app.ActivityThread",这就是进程初始化时要加载的Java类了,把这个类加载到进程之后,就会把它里面的静态成员函数main作为进程的入口点,后面我们会看到。

Step 2. Process.start

这个函数定义在frameworks/base/core/java/android/os/Process.java文件中:

view plain
  1. publicclassProcess{
  2. ......
  3. publicstaticfinalintstart(finalStringprocessClass,
  4. finalStringniceName,
  5. intuid,intgid,int[]gids,
  6. intdebugFlags,
  7. String[]zygoteArgs)
  8. {
  9. if(supportsProcesses()){
  10. try{
  11. returnstartViaZygote(processClass,niceName,uid,gid,gids,
  12. debugFlags,zygoteArgs);
  13. }catch(ZygoteStartFailedExex){
  14. ......
  15. }
  16. }else{
  17. ......
  18. return0;
  19. }
  20. }
  21. ......
  22. }
这里的supportsProcesses函数返回值为true,它是一个Native函数,实现在frameworks/base/core/jni/android_util_Process.cpp文件中:
view plain
  1. jbooleanandroid_os_Process_supportsProcesses(JNIEnv*env,jobjectclazz)
  2. {
  3. returnProcessState::self()->supportsProcesses();
  4. }

ProcessState::supportsProcesses函数定义在frameworks/base/libs/binder/ProcessState.cpp文件中:

view plain
  1. boolProcessState::supportsProcesses()const
  2. {
  3. returnmDriverFD>=0;
  4. }
这里的mDriverFD是设备文件/dev/binder的打开描述符,如果成功打开了这个设备文件,那么它的值就会大于等于0,因此,它的返回值为true。

回到Process.start函数中,它调用startViaZygote函数进一步操作。

Step 3.Process.startViaZygote

这个函数定义在frameworks/base/core/java/android/os/Process.java文件中:

view plain
  1. publicclassProcess{
  2. ......
  3. privatestaticintstartViaZygote(finalStringprocessClass,
  4. finalStringniceName,
  5. finalintuid,finalintgid,
  6. finalint[]gids,
  7. intdebugFlags,
  8. String[]extraArgs)
  9. throwsZygoteStartFailedEx{
  10. intpid;
  11. synchronized(Process.class){
  12. ArrayList<String>argsForZygote=newArrayList<String>();
  13. //--runtime-init,--setuid=,--setgid=,
  14. //and--setgroups=mustgofirst
  15. argsForZygote.add("--runtime-init");
  16. argsForZygote.add("--setuid="+uid);
  17. argsForZygote.add("--setgid="+gid);
  18. if((debugFlags&Zygote.DEBUG_ENABLE_SAFEMODE)!=0){
  19. argsForZygote.add("--enable-safemode");
  20. }
  21. if((debugFlags&Zygote.DEBUG_ENABLE_DEBUGGER)!=0){
  22. argsForZygote.add("--enable-debugger");
  23. }
  24. if((debugFlags&Zygote.DEBUG_ENABLE_CHECKJNI)!=0){
  25. argsForZygote.add("--enable-checkjni");
  26. }
  27. if((debugFlags&Zygote.DEBUG_ENABLE_ASSERT)!=0){
  28. argsForZygote.add("--enable-assert");
  29. }
  30. //TODOoptionallyenabledebuger
  31. //argsForZygote.add("--enable-debugger");
  32. //--setgroupsisacomma-separatedlist
  33. if(gids!=null&&gids.length>0){
  34. StringBuildersb=newStringBuilder();
  35. sb.append("--setgroups=");
  36. intsz=gids.length;
  37. for(inti=0;i<sz;i++){
  38. if(i!=0){
  39. sb.append(',');
  40. }
  41. sb.append(gids[i]);
  42. }
  43. argsForZygote.add(sb.toString());
  44. }
  45. if(niceName!=null){
  46. argsForZygote.add("--nice-name="+niceName);
  47. }
  48. argsForZygote.add(processClass);
  49. if(extraArgs!=null){
  50. for(Stringarg:extraArgs){
  51. argsForZygote.add(arg);
  52. }
  53. }
  54. pid=zygoteSendArgsAndGetPid(argsForZygote);
  55. }
  56. }
  57. ......
  58. }
这个函数将创建进程的参数放到argsForZygote列表中去,如参数"--runtime-init"表示要为新创建的进程初始化运行时库,然后调用zygoteSendAndGetPid函数进一步操作。

Step 4. Process.zygoteSendAndGetPid

这个函数定义在frameworks/base/core/java/android/os/Process.java文件中:

view plain
  1. publicclassProcess{
  2. ......
  3. privatestaticintzygoteSendArgsAndGetPid(ArrayList<String>args)
  4. throwsZygoteStartFailedEx{
  5. intpid;
  6. openZygoteSocketIfNeeded();
  7. try{
  8. /**
  9. *Seecom.android.internal.os.ZygoteInit.readArgumentList()
  10. *Presentlythewireformattothezygoteprocessis:
  11. *a)acountofarguments(argc,inessence)
  12. *b)anumberofnewline-separatedargumentstringsequaltocount
  13. *
  14. *Afterthezygoteprocessreadstheseitwillwritethepidof
  15. *thechildor-1onfailure.
  16. */
  17. sZygoteWriter.write(Integer.toString(args.size()));
  18. sZygoteWriter.newLine();
  19. intsz=args.size();
  20. for(inti=0;i<sz;i++){
  21. Stringarg=args.get(i);
  22. if(arg.indexOf('\n')>=0){
  23. thrownewZygoteStartFailedEx(
  24. "embeddednewlinesnotallowed");
  25. }
  26. sZygoteWriter.write(arg);
  27. sZygoteWriter.newLine();
  28. }
  29. sZygoteWriter.flush();
  30. //Shouldtherebeatimeoutonthis?
  31. pid=sZygoteInputStream.readInt();
  32. if(pid<0){
  33. thrownewZygoteStartFailedEx("fork()failed");
  34. }
  35. }catch(IOExceptionex){
  36. ......
  37. }
  38. returnpid;
  39. }
  40. ......
  41. }
这里的sZygoteWriter是一个Socket写入流,是由openZygoteSocketIfNeeded函数打开的:
view plain
  1. publicclassProcess{
  2. ......
  3. /**
  4. *TriestoopensockettoZygoteprocessifnotalreadyopen.If
  5. *alreadyopen,doesnothing.Mayblockandretry.
  6. */
  7. privatestaticvoidopenZygoteSocketIfNeeded()
  8. throwsZygoteStartFailedEx{
  9. intretryCount;
  10. if(sPreviousZygoteOpenFailed){
  11. /*
  12. *Ifwe'vefailedbefore,expectthatwe'llfailagainand
  13. *don'tpauseforretries.
  14. */
  15. retryCount=0;
  16. }else{
  17. retryCount=10;
  18. }
  19. /*
  20. *Seebug#811181:Sometimesruntimecanmakeitupbeforezygote.
  21. *Really,we'dliketodosomethingbettertoavoidthiscondition,
  22. *butfornowjustwaitabit...
  23. */
  24. for(intretry=0
  25. ;(sZygoteSocket==null)&&(retry<(retryCount+1))
  26. ;retry++){
  27. if(retry>0){
  28. try{
  29. Log.i("Zygote","Zygotenotupyet,sleeping...");
  30. Thread.sleep(ZYGOTE_RETRY_MILLIS);
  31. }catch(InterruptedExceptionex){
  32. //shouldneverhappen
  33. }
  34. }
  35. try{
  36. sZygoteSocket=newLocalSocket();
  37. sZygoteSocket.connect(newLocalSocketAddress(ZYGOTE_SOCKET,
  38. LocalSocketAddress.Namespace.RESERVED));
  39. sZygoteInputStream
  40. =newDataInputStream(sZygoteSocket.getInputStream());
  41. sZygoteWriter=
  42. newBufferedWriter(
  43. newOutputStreamWriter(
  44. sZygoteSocket.getOutputStream()),
  45. 256);
  46. Log.i("Zygote","Process:zygotesocketopened");
  47. sPreviousZygoteOpenFailed=false;
  48. break;
  49. }catch(IOExceptionex){
  50. ......
  51. }
  52. }
  53. ......
  54. }
  55. ......
  56. }
这个Socket由frameworks/base/core/java/com/android/internal/os/ZygoteInit.java文件中的ZygoteInit类在runSelectLoopMode函数侦听的。
Step 5.ZygoteInit.runSelectLoopMode
这个函数定义在frameworks/base/core/java/com/android/internal/os/ZygoteInit.java文件中:
view plain
  1. publicclassZygoteInit{
  2. ......
  3. /**
  4. *Runsthezygoteprocess'sselectloop.Acceptsnewconnectionsas
  5. *theyhappen,andreadscommandsfromconnectionsonespawn-request's
  6. *worthatatime.
  7. *
  8. *@throwsMethodAndArgsCallerinachildprocesswhenamain()should
  9. *beexecuted.
  10. */
  11. privatestaticvoidrunSelectLoopMode()throwsMethodAndArgsCaller{
  12. ArrayList<FileDescriptor>fds=newArrayList();
  13. ArrayList<ZygoteConnection>peers=newArrayList();
  14. FileDescriptor[]fdArray=newFileDescriptor[4];
  15. fds.add(sServerSocket.getFileDescriptor());
  16. peers.add(null);
  17. intloopCount=GC_LOOP_COUNT;
  18. while(true){
  19. intindex;
  20. /*
  21. *Callgc()beforeweblockinselect().
  22. *It'sworkthathastobedoneanyway,andit'sbetter
  23. *toavoidmakingeverychilddoit.Itwillalso
  24. *madvise()anyfreememoryasaside-effect.
  25. *
  26. *Don'tcalliteverytime,becausewalkingtheentire
  27. *heapisalotofoverheadtofreeafewhundredbytes.
  28. */
  29. if(loopCount<=0){
  30. gc();
  31. loopCount=GC_LOOP_COUNT;
  32. }else{
  33. loopCount--;
  34. }
  35. try{
  36. fdArray=fds.toArray(fdArray);
  37. index=selectReadable(fdArray);
  38. }catch(IOExceptionex){
  39. thrownewRuntimeException("Errorinselect()",ex);
  40. }
  41. if(index<0){
  42. thrownewRuntimeException("Errorinselect()");
  43. }elseif(index==0){
  44. ZygoteConnectionnewPeer=acceptCommandPeer();
  45. peers.add(newPeer);
  46. fds.add(newPeer.getFileDesciptor());
  47. }else{
  48. booleandone;
  49. done=peers.get(index).runOnce();
  50. if(done){
  51. peers.remove(index);
  52. fds.remove(index);
  53. }
  54. }
  55. }
  56. }
  57. ......
  58. }
当Step 4将数据通过Socket接口发送出去后,就会下面这个语句:
view plain
  1. done=peers.get(index).runOnce();
这里从peers.get(index)得到的是一个ZygoteConnection对象,表示一个Socket连接,因此,接下来就是调用ZygoteConnection.runOnce函数进一步处理了。

Step 6.ZygoteConnection.runOnce

这个函数定义在frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java文件中:

view plain
  1. classZygoteConnection{
  2. ......
  3. booleanrunOnce()throwsZygoteInit.MethodAndArgsCaller{
  4. Stringargs[];
  5. ArgumentsparsedArgs=null;
  6. FileDescriptor[]descriptors;
  7. try{
  8. args=readArgumentList();
  9. descriptors=mSocket.getAncillaryFileDescriptors();
  10. }catch(IOExceptionex){
  11. ......
  12. returntrue;
  13. }
  14. ......
  15. /**thestderrofthemostrecentrequest,ifavail*/
  16. PrintStreamnewStderr=null;
  17. if(descriptors!=null&&descriptors.length>=3){
  18. newStderr=newPrintStream(
  19. newFileOutputStream(descriptors[2]));
  20. }
  21. intpid;
  22. try{
  23. parsedArgs=newArguments(args);
  24. applyUidSecurityPolicy(parsedArgs,peer);
  25. applyDebuggerSecurityPolicy(parsedArgs);
  26. applyRlimitSecurityPolicy(parsedArgs,peer);
  27. applyCapabilitiesSecurityPolicy(parsedArgs,peer);
  28. int[][]rlimits=null;
  29. if(parsedArgs.rlimits!=null){
  30. rlimits=parsedArgs.rlimits.toArray(intArray2d);
  31. }
  32. pid=Zygote.forkAndSpecialize(parsedArgs.uid,parsedArgs.gid,
  33. parsedArgs.gids,parsedArgs.debugFlags,rlimits);
  34. }catch(IllegalArgumentExceptionex){
  35. ......
  36. }catch(ZygoteSecurityExceptionex){
  37. ......
  38. }
  39. if(pid==0){
  40. //inchild
  41. handleChildProc(parsedArgs,descriptors,newStderr);
  42. //shouldneverhappen
  43. returntrue;
  44. }else{/*pid!=0*/
  45. //inparent...pidof<0meansfailure
  46. returnhandleParentProc(pid,descriptors,parsedArgs);
  47. }
  48. }
  49. ......
  50. }
真正创建进程的地方就是在这里了:
view plain
  1. pid=Zygote.forkAndSpecialize(parsedArgs.uid,parsedArgs.gid,
  2. parsedArgs.gids,parsedArgs.debugFlags,rlimits);
有Linux开发经验的读者很容易看懂这个函数调用,这个函数会创建一个进程,而且有两个返回值,一个是在当前进程中返回的,一个是在新创建的进程中返回,即在当前进程的子进程中返回,在当前进程中的返回值就是新创建的子进程的pid值,而在子进程中的返回值是0。因为我们只关心创建的新进程的情况,因此,我们沿着子进程的执行路径继续看下去:
view plain
  1. if(pid==0){
  2. //inchild
  3. handleChildProc(parsedArgs,descriptors,newStderr);
  4. //shouldneverhappen
  5. returntrue;
  6. }else{/*pid!=0*/
  7. ......
  8. }
这里就是调用handleChildProc函数了。

Step 7.ZygoteConnection.handleChildProc
这个函数定义在frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java文件中:

view plain
  1. classZygoteConnection{
  2. ......
  3. privatevoidhandleChildProc(ArgumentsparsedArgs,
  4. FileDescriptor[]descriptors,PrintStreamnewStderr)
  5. throwsZygoteInit.MethodAndArgsCaller{
  6. ......
  7. if(parsedArgs.runtimeInit){
  8. RuntimeInit.zygoteInit(parsedArgs.remainingArgs);
  9. }else{
  10. ......
  11. }
  12. }
  13. ......
  14. }
由于在前面的Step 3中,指定了"--runtime-init"参数,表示要为新创建的进程初始化运行时库,因此,这里的parseArgs.runtimeInit值为true,于是就继续执行RuntimeInit.zygoteInit进一步处理了。

Step 8.RuntimeInit.zygoteInit

这个函数定义在frameworks/base/core/java/com/android/internal/os/RuntimeInit.java文件中:

view plain
  1. publicclassRuntimeInit{
  2. ......
  3. publicstaticfinalvoidzygoteInit(String[]argv)
  4. throwsZygoteInit.MethodAndArgsCaller{
  5. //TODO:Doingthishereworks,butitseemskindofarbitrary.Find
  6. //abetterplace.Thegoalistosetitupforapplications,butnot
  7. //toolslikeam.
  8. System.setOut(newAndroidPrintStream(Log.INFO,"System.out"));
  9. System.setErr(newAndroidPrintStream(Log.WARN,"System.err"));
  10. commonInit();
  11. zygoteInitNative();
  12. intcurArg=0;
  13. for(/*curArg*/;curArg<argv.length;curArg++){
  14. Stringarg=argv[curArg];
  15. if(arg.equals("--")){
  16. curArg++;
  17. break;
  18. }elseif(!arg.startsWith("--")){
  19. break;
  20. }elseif(arg.startsWith("--nice-name=")){
  21. StringniceName=arg.substring(arg.indexOf('=')+1);
  22. Process.setArgV0(niceName);
  23. }
  24. }
  25. if(curArg==argv.length){
  26. Slog.e(TAG,"MissingclassnameargumenttoRuntimeInit!");
  27. //lettheprocessexit
  28. return;
  29. }
  30. //Remainingargumentsarepassedtothestartclass'sstaticmain
  31. StringstartClass=argv[curArg++];
  32. String[]startArgs=newString[argv.length-curArg];
  33. System.arraycopy(argv,curArg,startArgs,0,startArgs.length);
  34. invokeStaticMain(startClass,startArgs);
  35. }
  36. ......
  37. }
这里有两个关键的函数调用,一个是zygoteInitNative函数调用,一个是invokeStaticMain函数调用,前者就是执行Binder驱动程序初始化的相关工作了,正是由于执行了这个工作,才使得进程中的Binder对象能够顺利地进行Binder进程间通信,而后一个函数调用,就是执行进程的入口函数,这里就是执行startClass类的main函数了,而这个startClass即是我们在Step 1中传进来的"android.app.ActivityThread"值,表示要执行android.app.ActivityThread类的main函数。

我们先来看一下zygoteInitNative函数的调用过程,然后再回到RuntimeInit.zygoteInit函数中来,看看它是如何调用android.app.ActivityThread类的main函数的。

step 9.RuntimeInit.zygoteInitNative

这个函数定义在frameworks/base/core/java/com/android/internal/os/RuntimeInit.java文件中:

view plain
  1. publicclassRuntimeInit{
  2. ......
  3. publicstaticfinalnativevoidzygoteInitNative();
  4. ......
  5. }
这里可以看出,函数zygoteInitNative是一个Native函数,实现在frameworks/base/core/jni/AndroidRuntime.cpp文件中:
view plain
  1. staticvoidcom_android_internal_os_RuntimeInit_zygoteInit(JNIEnv*env,jobjectclazz)
  2. {
  3. gCurRuntime->onZygoteInit();
  4. }

这里它调用了全局变量gCurRuntime的onZygoteInit函数,这个全局变量的定义在frameworks/base/core/jni/AndroidRuntime.cpp文件开头的地方:

view plain
  1. staticAndroidRuntime*gCurRuntime=NULL;
这里可以看出,它的类型为AndroidRuntime,它是在AndroidRuntime类的构造函数中初始化的,AndroidRuntime类的构造函数也是定义在frameworks/base/core/jni/AndroidRuntime.cpp文件中:
view plain
  1. AndroidRuntime::AndroidRuntime()
  2. {
  3. ......
  4. assert(gCurRuntime==NULL);//oneperprocess
  5. gCurRuntime=this;
  6. }
那么这个AndroidRuntime类的构造函数又是什么时候被调用的呢?AndroidRuntime类的声明在frameworks/base/include/android_runtime/AndroidRuntime.h文件中,如果我们打开这个文件会看到,它是一个虚拟类,也就是我们不能直接创建一个AndroidRuntime对象,只能用一个AndroidRuntime类的指针来指向它的某一个子类,这个子类就是AppRuntime了,它定义在frameworks/base/cmds/app_process/app_main.cpp文件中:
view plain
  1. intmain(intargc,constchar*constargv[])
  2. {
  3. ......
  4. AppRuntimeruntime;
  5. ......
  6. }
而AppRuntime类继续了AndroidRuntime类,它也是定义在frameworks/base/cmds/app_process/app_main.cpp文件中:
view plain
  1. classAppRuntime:publicAndroidRuntime
  2. {
  3. ......
  4. };
因此,在前面的com_android_internal_os_RuntimeInit_zygoteInit函数,实际是执行了AppRuntime类的onZygoteInit函数。

Step 10.AppRuntime.onZygoteInit
这个函数定义在frameworks/base/cmds/app_process/app_main.cpp文件中:

view plain
  1. classAppRuntime:publicAndroidRuntime
  2. {
  3. ......
  4. virtualvoidonZygoteInit()
  5. {
  6. sp<ProcessState>proc=ProcessState::self();
  7. if(proc->supportsProcesses()){
  8. LOGV("Appprocess:startingthreadpool.\n");
  9. proc->startThreadPool();
  10. }
  11. }
  12. ......
  13. };
这里它就是调用ProcessState::startThreadPool启动线程池了,这个线程池中的线程就是用来和Binder驱动程序进行交互的了。
Step 11.ProcessState.startThreadPool
这个函数定义在frameworks/base/libs/binder/ProcessState.cpp文件中:
view plain
  1. voidProcessState::startThreadPool()
  2. {
  3. AutoMutex_l(mLock);
  4. if(!mThreadPoolStarted){
  5. mThreadPoolStarted=true;
  6. spawnPooledThread(true);
  7. }
  8. }
ProcessState类是Binder进程间通信机制的一个基础组件,它的作用可以参考浅谈Android系统进程间通信(IPC)机制Binder中的Server和Client获得Service Manager接口之路、Android系统进程间通信(IPC)机制Binder中的Server启动过程源代码分析和Android系统进程间通信(IPC)机制Binder中的Client获得Server远程接口过程源代码分析这三篇文章。这里它调用spawnPooledThread函数进一步处理。

Step 12.ProcessState.spawnPooledThread

这个函数定义在frameworks/base/libs/binder/ProcessState.cpp文件中:

view plain
  1. voidProcessState::spawnPooledThread(boolisMain)
  2. {
  3. if(mThreadPoolStarted){
  4. int32_ts=android_atomic_add(1,&mThreadPoolSeq);
  5. charbuf[32];
  6. sprintf(buf,"BinderThread#%d",s);
  7. LOGV("Spawningnewpooledthread,name=%s\n",buf);
  8. sp<Thread>t=newPoolThread(isMain);
  9. t->run(buf);
  10. }
  11. }
这里它会创建一个PoolThread线程类,然后执行它的run函数,最终就会执行PoolThread类的threadLoop函数了。

Step 13.PoolThread.threadLoop

这个函数定义在frameworks/base/libs/binder/ProcessState.cpp文件中:

view plain
  1. classPoolThread:publicThread
  2. {
  3. public:
  4. PoolThread(boolisMain)
  5. :mIsMain(isMain)
  6. {
  7. }
  8. protected:
  9. virtualboolthreadLoop()
  10. {
  11. IPCThreadState::self()->joinThreadPool(mIsMain);
  12. returnfalse;
  13. }
  14. constboolmIsMain;
  15. };
这里它执行了IPCThreadState::joinThreadPool函数进一步处理。IPCThreadState也是Binder进程间通信机制的一个基础组件,它的作用可以参考浅谈Android系统进程间通信(IPC)机制Binder中的Server和Client获得Service Manager接口之路、Android系统进程间通信(IPC)机制Binder中的Server启动过程源代码分析和Android系统进程间通信(IPC)机制Binder中的Client获得Server远程接口过程源代码分析这三篇文章。

Step 14.IPCThreadState.joinThreadPool

这个函数定义在frameworks/base/libs/binder/IPCThreadState.cpp文件中:

view plain
  1. voidIPCThreadState::joinThreadPool(boolisMain)
  2. {
  3. ......
  4. mOut.writeInt32(isMain?BC_ENTER_LOOPER:BC_REGISTER_LOOPER);
  5. ......
  6. status_tresult;
  7. do{
  8. int32_tcmd;
  9. ......
  10. //nowgetthenextcommandtobeprocessed,waitingifnecessary
  11. result=talkWithDriver();
  12. if(result>=NO_ERROR){
  13. size_tIN=mIn.dataAvail();
  14. if(IN<sizeof(int32_t))continue;
  15. cmd=mIn.readInt32();
  16. ......
  17. result=executeCommand(cmd);
  18. }
  19. ......
  20. }while(result!=-ECONNREFUSED&&result!=-EBADF);
  21. ......
  22. mOut.writeInt32(BC_EXIT_LOOPER);
  23. talkWithDriver(false);
  24. }
这个函数首先告诉Binder驱动程序,这条线程要进入循环了:
view plain
  1. mOut.writeInt32(isMain?BC_ENTER_LOOPER:BC_REGISTER_LOOPER);
然后在中间的while循环中通过talkWithDriver不断与Binder驱动程序进行交互,以便获得Client端的进程间调用:
view plain
  1. result=talkWithDriver();
获得了Client端的进程间调用后,就调用excuteCommand函数来处理这个请求:
view plain
  1. result=executeCommand(cmd);
最后,线程退出时,也会告诉Binder驱动程序,它退出了,这样Binder驱动程序就不会再在Client端的进程间调用分发给它了:
view plain
  1. mOut.writeInt32(BC_EXIT_LOOPER);
  2. talkWithDriver(false);
我们再来看看talkWithDriver函数的实现。

Step 15. talkWithDriver

这个函数定义在frameworks/base/libs/binder/IPCThreadState.cpp文件中:

view plain
  1. status_tIPCThreadState::talkWithDriver(booldoReceive)
  2. {
  3. ......
  4. binder_write_readbwr;
  5. //Isthereadbufferempty?
  6. constboolneedRead=mIn.dataPosition()>=mIn.dataSize();
  7. //Wedon'twanttowriteanythingifwearestillreading
  8. //fromdataleftintheinputbufferandthecaller
  9. //hasrequestedtoreadthenextdata.
  10. constsize_toutAvail=(!doReceive||needRead)?mOut.dataSize():0;
  11. bwr.write_size=outAvail;
  12. bwr.write_buffer=(longunsignedint)mOut.data();
  13. //Thisiswhatwe'llread.
  14. if(doReceive&&needRead){
  15. bwr.read_size=mIn.dataCapacity();
  16. bwr.read_buffer=(longunsignedint)mIn.data();
  17. }else{
  18. bwr.read_size=0;
  19. }
  20. ......
  21. //Returnimmediatelyifthereisnothingtodo.
  22. if((bwr.write_size==0)&&(bwr.read_size==0))returnNO_ERROR;
  23. bwr.write_consumed=0;
  24. bwr.read_consumed=0;
  25. status_terr;
  26. do{
  27. ......
  28. #ifdefined(HAVE_ANDROID_OS)
  29. if(ioctl(mProcess->mDriverFD,BINDER_WRITE_READ,&bwr)>=0)
  30. err=NO_ERROR;
  31. else
  32. err=-errno;
  33. #else
  34. err=INVALID_OPERATION;
  35. #endif
  36. ......
  37. }
  38. }while(err==-EINTR);
  39. ....
  40. if(err>=NO_ERROR){
  41. if(bwr..write_consumed>0){
  42. if(bwr.write_consumed<(ssize_t)mOut.dataSize())
  43. mOut.remove(0,bwr.write_consumed);
  44. else
  45. mOut.setDataSize(0);
  46. }
  47. if(bwr.read_consumed>0){
  48. mIn.setDataSize(bwr.read_consumed);
  49. mIn.setDataPosition(0);
  50. }
  51. ......
  52. returnNO_ERROR;
  53. }
  54. returnerr;
  55. }
这个函数的具体作用可以参考Android系统进程间通信(IPC)机制Binder中的Server启动过程源代码分析一文,它只要就是通过ioctl文件操作函数来和Binder驱动程序交互的了:
view plain
  1. ioctl(mProcess->mDriverFD,BINDER_WRITE_READ,&bwr)
有了这个线程池之后,我们在开发Android应用程序的时候,当我们要和其它进程中进行通信时,只要定义自己的Binder对象,然后把这个Binder对象的远程接口通过其它途径传给其它进程后,其它进程就可以通过这个Binder对象的远程接口来调用我们的应用程序进程的函数了,它不像我们在C++层实现Binder进程间通信机制的Server时,必须要手动调用IPCThreadState.joinThreadPool函数来进入一个无限循环中与Binder驱动程序交互以便获得Client端的请求,这样就实现了我们在文章开头处说的Android应用程序进程天然地支持Binder进程间通信机制。

细心的读者可能会发现,从Step 1到Step 9,都是在Android应用程序框架层运行的,而从Step 10到Step 15,都是在Android系统运行时库层运行的,这两个层次中的Binder进程间通信机制的接口一个是用Java来实现的,而别一个是用C++来实现的,这两者是如何协作的呢?这就是通过JNI层来实现的了,具体可以参考Android系统进程间通信Binder机制在应用程序框架层的Java接口源代码分析一文。

回到Step 8中的RuntimeInit.zygoteInit函数中,在初始化完成Binder进程间通信机制的基础设施后,它接着就要进入进程的入口函数了。

Step 16.RuntimeInit.invokeStaticMain

这个函数定义在frameworks/base/core/java/com/android/internal/os/RuntimeInit.java文件中:

view plain
  1. publicclassZygoteInit{
  2. ......
  3. staticvoidinvokeStaticMain(ClassLoaderloader,
  4. StringclassName,String[]argv)
  5. throwsZygoteInit.MethodAndArgsCaller{
  6. Class<?>cl;
  7. try{
  8. cl=loader.loadClass(className);
  9. }catch(ClassNotFoundExceptionex){
  10. ......
  11. }
  12. Methodm;
  13. try{
  14. m=cl.getMethod("main",newClass[]{String[].class});
  15. }catch(NoSuchMethodExceptionex){
  16. ......
  17. }catch(SecurityExceptionex){
  18. ......
  19. }
  20. intmodifiers=m.getModifiers();
  21. ......
  22. /*
  23. *ThisthrowgetscaughtinZygoteInit.main(),whichresponds
  24. *byinvokingtheexception'srun()method.Thisarrangement
  25. *clearsupallthestackframesthatwererequiredinsetting
  26. *uptheprocess.
  27. */
  28. thrownewZygoteInit.MethodAndArgsCaller(m,argv);
  29. }
  30. ......
  31. }
前面我们说过,这里传进来的参数className字符串值为"android.app.ActivityThread",这里就通ClassLoader.loadClass函数将它加载到进程中:
view plain
  1. cl=loader.loadClass(className);
然后获得它的静态成员函数main:
view plain
  1. m=cl.getMethod("main",newClass[]{String[].class});
函数最后并没有直接调用这个静态成员函数main,而是通过抛出一个异常ZygoteInit.MethodAndArgsCaller,然后让ZygoteInit.main函数在捕获这个异常的时候再调用android.app.ActivityThread类的main函数。为什么要这样做呢?注释里面已经讲得很清楚了,它是为了清理堆栈的,这样就会让android.app.ActivityThread类的main函数觉得自己是进程的入口函数,而事实上,在执行android.app.ActivityThread类的main函数之前,已经做了大量的工作了。

我们看看ZygoteInit.main函数在捕获到这个异常的时候做了什么事:

view plain
  1. publicclassZygoteInit{
  2. ......
  3. publicstaticvoidmain(Stringargv[]){
  4. try{
  5. ......
  6. }catch(MethodAndArgsCallercaller){
  7. caller.run();
  8. }catch(RuntimeExceptionex){
  9. ......
  10. }
  11. }
  12. ......
  13. }
它执行MethodAndArgsCaller的run函数:
view plain
  1. publicclassZygoteInit{
  2. ......
  3. publicstaticclassMethodAndArgsCallerextendsException
  4. implementsRunnable{
  5. /**methodtocall*/
  6. privatefinalMethodmMethod;
  7. /**argumentarray*/
  8. privatefinalString[]mArgs;
  9. publicMethodAndArgsCaller(Methodmethod,String[]args){
  10. mMethod=method;
  11. mArgs=args;
  12. }
  13. publicvoidrun(){
  14. try{
  15. mMethod.invoke(null,newObject[]{mArgs});
  16. }catch(IllegalAccessExceptionex){
  17. ......
  18. }catch(InvocationTargetExceptionex){
  19. ......
  20. }
  21. }
  22. }
  23. ......
  24. }
这里的成员变量mMethod和mArgs都是在前面构造异常对象时传进来的,这里的mMethod就对应android.app.ActivityThread类的main函数了,于是最后就通过下面语句执行这个函数:
view plain
  1. mMethod.invoke(null,newObject[]{mArgs});
这样,android.app.ActivityThread类的main函数就被执行了。

Step 17.ActivityThread.main

这个函数定义在frameworks/base/core/java/android/app/ActivityThread.java文件中:

view plain
  1. publicfinalclassActivityThread{
  2. ......
  3. publicstaticfinalvoidmain(String[]args){
  4. SamplingProfilerIntegration.start();
  5. Process.setArgV0("<pre-initialized>");
  6. Looper.prepareMainLooper();
  7. if(sMainThreadHandler==null){
  8. sMainThreadHandler=newHandler();
  9. }
  10. ActivityThreadthread=newActivityThread();
  11. thread.attach(false);
  12. if(false){
  13. Looper.myLooper().setMessageLogging(new
  14. LogPrinter(Log.DEBUG,"ActivityThread"));
  15. }
  16. Looper.loop();
  17. if(Process.supportsProcesses()){
  18. thrownewRuntimeException("Mainthreadloopunexpectedlyexited");
  19. }
  20. thread.detach();
  21. Stringname=(thread.mInitialApplication!=null)
  22. ?thread.mInitialApplication.getPackageName()
  23. :"<unknown>";
  24. Slog.i(TAG,"Mainthreadof"+name+"isnowexiting");
  25. }
  26. ......
  27. }
从这里我们可以看出,这个函数首先会在进程中创建一个ActivityThread对象:
view plain
  1. ActivityThreadthread=newActivityThread();
然后进入消息循环中:
view plain
  1. Looper.loop();
这样,我们以后就可以在这个进程中启动Activity或者Service了。

至此,Android应用程序进程启动过程的源代码就分析完成了,它除了指定新的进程的入口函数是ActivityThread的main函数之外,还为进程内的Binder对象提供了Binder进程间通信机制的基础设施,由此可见,Binder进程间通信机制在Android系统中是何等的重要,而且是无处不在,想进一步学习Android系统的Binder进程间通信机制,请参考Android进程间通信(IPC)机制Binder简要介绍和学习计划一文。


分享到:
评论

相关推荐

    Android应用程序进程启动过程的源代码分析.pdf

    Android应用程序进程启动过程的源代码分析.pdf

    老罗的android之旅时序图

    Android应用程序绑定服务(bindService)的过程源代码分析UML.jpg,Android应用程序进程启动过程的源代码分析uml.jpg,Android应用程序内部启动Activity过程(startActivity)的源代码分析 UML.jpg,Android应用程序...

    Android应用程序启动过程源代码分析

    在Android系统中,应用程序是由Activity组成的,因此,应用程序的启动过程实际上就是应用程序中的默认Activity的启动过程,本文将详细分析应用程序框架层的源代码,了解Android应用程序的启动过程。在上一篇文章...

    《Android系统源代码情景分析》

    第12章 Android应用程序进程的启动过程 12.1 应用程序进程的创建过程 12.2 Binder线程池的启动过程 12.3 消息循环的创建过程 第13章 Android应用程序的消息处理机制 13.1 创建线程消息队列 13.2 线程...

    Android系统源代码情景分析 / 罗升阳著

    第12章 Android应用程序进程的启动过程 第13章 Android应用程序的消息处理机制 第14章 Android应用程序的键盘消息处理机制 第15章 Android应用程序线程的消息循环模型 第16章 Android应用程序的安装和显示过程

    Android系统源代码情景分析-罗升阳-源码

    第12章 Android应用程序进程的启动过程 12.1 应用程序进程的创建过程 12.2 Binder线程池的启动过程 12.3 消息循环的创建过程 第13章 Android应用程序的消息处理机制 13.1 创建线程消息队列 13.2 线程消息循环...

    Android高级编程--源代码

    3.1 Android应用程序的组成部分 43 3.2 程序清单简介 44 3.3 使用清单编辑器 47 3.4 Android应用程序生命周期 48 3.5 理解应用程序的优先级和进程状态 49 3.6 分离资源 50 3.6.1 创建资源 50 3.6.2 使用资源...

    Android系统源代码情景分析光盘

    Android系统源代码情景分析光盘资料 目录 第1篇初识Android系统 第1章 准备知识................................................................ 2 1.1 Linux内核参考书籍......................................

    Android移动应用开发(第3版)卷Ⅰ基础篇 (Shane Conder, Lauren Darcey) PDF扫描版

     《Android移动应用开发(第3版)卷Ⅰ:基础篇》涵盖了Android开发从概念、技术到市场推广应用的全部主题,内容包括Android平台概览、Android应用程序设计精髓、Android用户界面设计精髓、Android应用程序设计精髓、...

    Android代码-android-advanced-decode

    第3章介绍应用程序进程启动过程。 第4章介绍四大组件的工作过程,包括根Activity的启动过程,Service的启动和绑定过程,广播的注册、发送和接收过程,Content Provider的启动过程。 第5章从源码角度分析上下文...

    分析Android Activity的启动过程

    分析Android Activity的启动过程  对于Android Activity 的启动过程...根Activity一般就是指我们项目中的MainActivity,代表了一个android应用程序,一般也是在一个新的进程中启动起来。在Android系统中,所有的Activi

    Android程序设计基础

     读者可以在自己的应用程序中随意使用源代码。  关于“快速阅读指南”  虽然大多数作者都希望读者阅读他们书中的每一句话,但我知道你可能不想这样做。你只希望阅读能够解决手头问题的部分,而在需要解决其他...

    android源码包集合1

    360新版特性界面源代码.rar aidl跨进程调用.rar ...Android模仿乐淘的应用程序分析源码.zip android电话、短信黑白名单拦截、电话录音.rar Android系统源码获取及编译.zip android项目实例 商业项目源代码.rar

    AndroidNativeDaemon:Android 应用程序的本机守护进程

    Android 原生守护进程Android 应用程序的本机守护进程,当它消失时自动启动您的服务。构建源您必须在您的机器上安装 。 将 C 源文件 (daemon.c) 和 Android.mk 文件复制到您的项目目录中。 在您的项目目录中,运行...

    Android开发案例驱动教程 配套代码

    《Android开发案例驱动教程》 配套代码。 注: 由于第12,13,14章代码太大,无法上传到一个包中。 这三节代码会放到其他压缩包中。 作者:关东升,赵志荣 Java或C++程序员转变成为Android程序员 采用案例驱动模式...

    android 完全中文版 开发应用详解

    13.2.3 使用am工具启动android应用程序 306 13.3 android应用程序示例 308 13.3.1 helloactivity程序 308 13.3.2 helloactivity的源代码结构 308 13.3.3 helloactivity的编译结构(源代码开发) 312 13.3.4 ...

    Android应用开发实例:手机安全卫士源码

    - 进程管理:列出系统中正在运行的程序;演示杀死软件 - 窗口小部件:添加桌面; - 流量统计:模拟器并不支持,在真机上才能演示,只做个UI效果; - 手机杀毒:检查手机安装的软件,发现那个是病毒,提醒用户就杀掉...

    android系统原理及开发要点详解

     第13章“Android应用程序概述及框架”,介绍Android应用程序层的基本概念和应用程序框架,这部分内容是Android自下而上的第4个层次,可以基于源代码或者SDK开发,它们之间的差别非常小。  第14章“Android应用...

    Google Android SDK开发范例大全(完整版)

    每个 Android 应用程序都在 Dalvik VM 的一个实例中运行,这个实例驻留在一个由 Linux 内核管理的进程中,如下图所示。 图 2. Dalvik VM Android 应用程序由一个或多个组件组成: 活动 具有可视 UI 的应用...

Global site tag (gtag.js) - Google Analytics