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

  ActivityManagerService启动新的进程是从其成员函数startProcessLocked开始的。  它调用了Process.start函数开始为应用程序创建新的进程,注意,它传入一个第一个参数为"android.app.ActivityThread",这就是进程初始化时要加载的Java类了,把这个类加载到进程之后,就会把它里面的静态成员函数main作为进程的入口点。这个函数定义在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中。

  1.             int pid = Process.start("android.app.ActivityThread",    
  2.                 mSimpleProcessManagement ? app.processName : null, uid, uid,    
  3.                 gids, debugFlags, null);    
这个函数将 ActivityManagerService通过Socket 与Zygote 建立连接,并将相应的参数传递过去。

    神!上帝造人的时候到了,这个时候将在Zygote 进程中创建一个进程(ActivityManagerService让Zygote 创建的进程真正创建进程的地方就是在这里了:



[java]  view plain copy
  1. pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid,  
  2.     parsedArgs.gids, parsedArgs.debugFlags, rlimits);  

有Linux开发经验的读者很容易看懂这个函数调用,这个函数会创建一个进程,而且有两个返回值,一个是在当前进程中返回的,一个是在新创建的进程中返回,即在当前进程的子进程中返回,在当前进程中的返回值就是新创建的子进程的pid值,而在子进程中的返回值是0。因为我们只关心创建的新进程的情况,因此,我们沿着子进程的执行路径继续看下去:

[java]  view plain copy
  1. pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid,  
  2.     parsedArgs.gids, parsedArgs.debugFlags, rlimits);  

[java]  view plain copy
  1.    if (pid == 0) {  
  2. // in child  
  3. handleChildProc(parsedArgs, descriptors, newStderr);  
  4. // should never happen  
  5. return true;  
[java]  view       handleChildProc里有两个关键的函数调用,一个是zygoteInitNative函数调用,一个是invokeStaticMain函数调用,前者就是执行Binder驱动程序初始化的相关工作了,正是由于执行了这个工作,才使得进程中的Binder对象能够顺利地进行Binder进程间通信,而后一个函数调用,就是执行进程的入口函数,这里就是执行startClass类的main函数了,而这个startClass即是我们在Step 1中传进来的"android.app.ActivityThread"值,表示要执行android.app.ActivityThread类的main函数。

  其中ZygoteInitNative函数通过层层调用建立binder 通讯机制如下:

[java]  view plain copy
  1. pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid,  
  2.     parsedArgs.gids, parsedArgs.debugFlags, rlimits);  

  1.         sp proc = ProcessState::self();  
  2.         if (proc->supportsProcesses()) {  
  3.             LOGV("App process: starting thread pool.\n");  
  4.             proc->startThreadPool();  
  5.         }  
  6.     }  
  7.   
  8.     ......  
  9. };  
        这里它就是调用ProcessState::startThreadPool启动线程池了,这个线程池中的线程就是用来和Binder驱动程序进行交互的了。

另外一个函数invokeStaticMain函数调用,就是实现ActivityThread 的加载,前面我们说过,这里传进来的参数className字符串值为"android.app.ActivityThread",这里就通ClassLoader.loadClass函数将它加载到进程中:

[java]  view plain copy
  1. cl = loader.loadClass(className);  
        然后获得它的静态成员函数main:

[java]  view plain copy
  1. m = cl.getMethod("main"new Class[] { String[].class });  
最后ActivityThread 建立消息循环,里面的Main 函数如下:


  1. public final class ActivityThread {  
  2.     ......  
  3.   
  4.     public static final void main(String[] args) {  
  5.         SamplingProfilerIntegration.start();  
  6.   
  7.         Process.setArgV0("");  
  8.   
  9.         Looper.prepareMainLooper();  
  10.         if (sMainThreadHandler == null) {  
  11.             sMainThreadHandler = new Handler();  
  12.         }  
  13.   
  14.         ActivityThread thread = new ActivityThread();  
  15.         thread.attach(false);  
  16.   
  17.         if (false) {  
  18.             Looper.myLooper().setMessageLogging(new  
  19.                 LogPrinter(Log.DEBUG, "ActivityThread"));  
  20.         }  
  21.         Looper.loop();  

更多相关文章

  1. C语言函数的递归(上)
  2. Android(安卓)bionic缺失pthread_cancel的解决方法
  3. 一篇文章看明白 Android(安卓)Service 启动过程
  4. Android(安卓)init源代码分析(1)概要分析
  5. Android(安卓)/ OPhone开发系列教程正在发布中……
  6. Android(安卓)清单目录application对应属性讲解
  7. Android(安卓)Intent的几种用法总结
  8. Android(安卓)ClassLoader
  9. Android(安卓)Support V4, V7, V13的作用与用法

随机推荐

  1. div底部随机5 px空间
  2. Outlook Express 无法读取Html邮件的解决
  3. 如何在SQL中写正则表达式(适用于Ms SQL S
  4. AngularJS ng-repeat项目水平到垂直
  5. HTML5 笔记之 HTML5 的常见用法介绍
  6. html2canvas 识别 svg 解决方案
  7. 你所不知道的html5与html中的那些事(一)
  8. 为什么2012年HTML5发展远未达预期
  9. 在HTML标签中显示很长一段文字,显示两行,多
  10. HTML中图片的截取一部分显示