前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android应用进程启动过程(前篇)

Android应用进程启动过程(前篇)

作者头像
用户1269200
发布2018-02-01 14:24:46
9900
发布2018-02-01 14:24:46
举报
文章被收录于专栏:刘望舒刘望舒

前言

在此前我讲过Android系统的启动流程,系统启动后,我们就比较关心应用程序是如何启动的,这一篇我们来一起学习Android7.0 应用程序进程启动过程,需要注意的是“应用程序进程启动过程”,而不是应用程序启动过程。关于应用程序启动过程,我会在后续系列的文章中讲到。希望阅读这篇文章前先阅读本文列出的相关文章,要不你一脸蒙蔽,就别怪我了。

1.应用程序进程概述

要想启动一个应用程序,首先要保证这个应用程序所需要的应用程序进程已经被启动。ActivityManagerService在启动应用程序时会检查这个应用程序需要的应用程序进程是否存在,不存在就会请求Zygote进程将需要的应用程序进程启动。在Android系统启动流程(二)解析Zygote进程这篇文章中,我提到了Zygote的Java框架层中,会创建一个Server端的Socket,这个Socket用来等待ActivityManagerService来请求Zygote来创建新的应用程序进程的。我们知道Zygote进程通过fock自身创建的应用程序进程,这样应用程序程序进程就会获得Zygote进程在启动时创建的虚拟机实例。当然,在应用程序创建过程中除了获取虚拟机实例,还可以获得Binder线程池和消息循环,这样运行在应用进程中应用程序就可以方便的使用Binder进行进程间通信以及消息处理机制了。关于Binder线程池和消息循环是如何启动或者创建的会在下一篇文章给出答案。先给出应用程序进程启动过程的时序图,然后对每一个步骤进行详细分析,如下图所示。

2.应用程序进程创建过程

发送创建应用程序进程请求

ActivityManagerService会通过调用startProcessLocked函数来向Zygote进程发送请求,如下所示。 frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

在注释1处的达到创建应用程序进程的用户ID,在注释2处对用户组ID:gids进行创建和赋值。注释3处如果entryPoint 为null则赋值为"android.app.ActivityThread"。在注释4处调用Process的start函数,将此前得到的应用程序进程用户ID和用户组ID传进去,第一个参数entryPoint我们得知是"android.app.ActivityThread",后文会再次提到它。接下来我们来查看Process的start函数,如下所示。 frameworks/base/core/java/android/os/Process.java

start函数中只调用了startViaZygote函数: frameworks/base/core/java/android/os/Process.java

在注释1处创建了字符串列表argsForZygote ,并将启动应用进程的启动参数保存在argsForZygote中,函数的最后会调用zygoteSendArgsAndGetResult函数,需要注意的是,zygoteSendArgsAndGetResult函数中第一个参数中调用了openZygoteSocketIfNeeded函数,而第二个参数是保存应用进程的启动参数的argsForZygote。zygoteSendArgsAndGetResult函数如下所示。 frameworks/base/core/java/android/os/Process.java

zygoteSendArgsAndGetResult函数主要做的就是将传入的应用进程的启动参数argsForZygote,写入到ZygoteState中,结合上文我们知道ZygoteState其实是由openZygoteSocketIfNeeded函数返回的,那么我们接着来看openZygoteSocketIfNeeded函数,代码如下所示。 frameworks/base/core/java/android/os/Process.java

在讲到Zygote进程启动过程时我们得知,在Zygote的main函数中会创建name为“zygote”的Server端Socket。在注释1处会调用ZygoteState的connect函数与名称为ZYGOTE_SOCKET的Socket建立连接,这里ZYGOTE_SOCKET的值为“zygote”。注释2处如果连接name为“zygote”的Socket返回的primaryZygoteState与当前的abi不匹配,则会在注释3处连接name为“zygote_secondary”的Socket。这两个Socket区别就是:name为"zygote”的Socket是运行在64位Zygote进程中的,而name为“zygote_secondary”的Socket则运行在32位Zygote进程中。既然应用程序进程是通过Zygote进程fock产生的,当要连接Zygote中的Socket时,也需要保证位数的一致。

接收请求并创建应用程序进程

Socket进行连接成功并匹配abi后会返回ZygoteState类型对象,我们在分析zygoteSendArgsAndGetResult函数中讲过,会将应用进程的启动参数argsForZygote写入到ZygoteState中,这样Zygote进程就会收到一个创建新的应用程序进程的请求,我们回到ZygoteInit的main函数,如下所示。

frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

这些内容在Android系统启动流程(二)解析Zygote进程讲过,但为了更好的理解我再讲一遍。注释1处通过registerZygoteSocket函数来创建一个Server端的Socket,这个name为”zygote”的Socket用来等待ActivityManagerService来请求Zygote来创建新的应用程序进程。注释2处用来预加载类和资源。注释3处用来启动SystemServer进程,这样系统的关键服务也会由SystemServer进程启动起来。注释4处调用runSelectLoop函数来等待ActivityManagerService的请求。我们就来查看runSelectLoop函数:

frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

当有ActivityManagerService的请求数据到来时会调用注释1处的代码,结合注释2处的代码,我们得知注释1处的代码其实是调用ZygoteConnection的runOnce函数来处理请求的数据:

frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java

在注释1处调用readArgumentList函数来获取应用程序进程的启动参数,并在注释2处将readArgumentList函数返回的字符串封装到Arguments对象parsedArgs中。注释3处调用Zygote的forkAndSpecialize函数来创建应用程序进程,参数为parsedArgs中存储的应用进程启动参数,返回值为pid。forkAndSpecialize函数主要是通过fork当前进程来创建一个子进程的,如果pid等于0,则说明是在新创建的子进程中执行的,就会调用handleChildProc函数来启动这个子进程也就是应用程序进程,如下所示。 frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java

handleChildProc函数中调用了RuntimeInit的zygoteInit函数,如下所示。 frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

注释1处会在新创建的应用程序进程中创建Binder线程池,这个在下一篇文章会详细介绍。在注释2处调用了applicationInit函数: frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

在applicationInit中会在注释1处调用invokeStaticMain函数,需要注意的是第一个参数args.startClass,这里指的就是此篇文章开头提到的参数:android.app.ActivityThread。接下来我们查看invokeStaticMain函数,如下所示。 frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

可以看到注释1处通过反射来获得android.app.ActivityThread类,接下来在注释2处来获得ActivityThread的main函数,并将main函数传入到注释3处的ZygoteInit中的MethodAndArgsCaller类的构造函数中,MethodAndArgsCaller类内部会通过反射调用ActivityThread的main函数,这样应用程序进程就创建完成了。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-03-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 刘望舒 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 1.应用程序进程概述
  • 2.应用程序进程创建过程
    • 发送创建应用程序进程请求
      • 接收请求并创建应用程序进程
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档