Android 启动过程分析--笔记缩减

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 在CODE上查看代码片 派生到我的代码片
  1. pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid,  
  2.     parsedArgs.gids, parsedArgs.debugFlags, rlimits);  

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

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid,  
  2.     parsedArgs.gids, parsedArgs.debugFlags, rlimits);  

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  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 在CODE上查看代码片 派生到我的代码片
  1. pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid,  
  2.     parsedArgs.gids, parsedArgs.debugFlags, rlimits);  

  1.         sp<ProcessState> 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 在CODE上查看代码片 派生到我的代码片
  1. cl = loader.loadClass(className);  
        然后获得它的静态成员函数main:

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  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("<pre-initialized>");  
  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();  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值