简要回顾先回顾一下Android系统的启动过程:
init进程fork出Zygote进程后,Zygote进程会创建一个服务端socket,等待AMS发起socket请求 。
同时,由Zygote进程fork出的SystemServer进程会启动各项系统服务,其中就包含了AMS,AMS会启动Launcher桌面,此时就可以等待用户点击App图标来启动应用进程了 。
文章插图
然后看下系统服务的启动,不管是由init进程启动的独立进程的系统服务如SurfaceFlinger,还是由SystemServer进程启动的非独立进程的系统服务如AMS,都是在ServiceManager进程中完成注册和获取的,在跨进程通信上使用了Android的binder机制 。
文章插图
ServiceManager进程本身也是一个系统服务,经过启动进程、启动binder机制、发布自己和等待请求4个步骤,就可以处理其他系统服务的获取和注册需求了 。
AMS发送socket请求Android应用进程的启动是被动式的,在Launcher桌面点击图标启动一个应用的组件如Activity时,如果Activity所在的进程不存在,就会创建并启动进程 。
点击App图标后经过层层调用会来到ActivityStackSupervisor的startSpecificActivityLocked方法 。
//ActivityStackSupervisor.JAVAfinal ActivityManagerService mService;void startSpecificActivityLocked(...) {//查找Activity所在的进程,ProcessRecord是用来封装进程信息的数据结构ProcessRecord app = mService.getProcessRecordLocked(...);//如果进程已启动,并且binder句柄IApplicationThread也拿到了,那就直接启动Activityif (app != null && app.thread != null) {realStartActivityLocked(r, app, andResume, checkConfig);return;}//否则,让AMS启动进程mService.startProcessLocked(...);}
app.thread并不是线程,而是一个binder句柄 。应用进程使用AMS需要拿到AMS的句柄IActivityManager,而系统需要通知应用和管理应用的生命周期,所以也需要持有应用进程的binder句柄IApplicationThread 。也就是说,他们互相持有彼此的binder句柄,来实现双向通信 。
文章插图
那IApplicationThread句柄是怎么传给AMS的呢?Zygote进程收到socket请求后会处理请求参数,执行ActivityThread的入口函数main 。
//ActivityThread.javapublic static void main(String[] args) {//创建主线程的looperLooper.prepareMainLooper();//ActivityThread并不是线程,只是普通的java对象ActivityThread thread = new ActivityThread();//告诉AMS,应用已经启动好了thread.attach(false);//运行looper,启动消息循环Looper.loop();}private void attach(boolean system) {//获取AMS的binder句柄IActivityManagerfinal IActivityManager mgr = ActivityManager.getService();//告诉AMS应用进程已经启动,并传入应用进程自己的binder句柄IApplicationThreadmgr.attachApplication(mAppThread);}
所以对于AMS来说:1.AMS向Zygote发起启动应用的socket请求,Zygote收到请求fork出进程,返回进程的pid给AMS;
2.应用进程启动好后,执行入口main函数,通过attachApplication方法告诉AMS已经启动,同时传入应用进程的binder句柄IApplicationThread 。
完成这两步,应用进程的启动过程才算完成 。
下面看AMS的startProcessLocked启动应用进程时都做了些什么 。
//ActivityManagerService.javafinal ProcessRecord startProcessLocked(...){ProcessRecord app = getProcessRecordLocked(processName, info.uid, keepIfLarge);//如果进程信息不为空,并且已经拿到了Zygote进程返回的应用进程pid//说明AMS已经请求过了,并且Zygote已经响应请求然后fork出进程了if (app != null && app.pid > 0) {//但是app.thread还是空,说明应用进程还没来得及注册自己的binder句柄给AMS//即此时进程正在启动,那就直接返回,避免重复创建if (app.thread == null) {return app;}}//调用重载方法startProcessLocked(...);}
之所以要判断app.thread,是为了避免当应用进程正在启动的时候,假如又有另一个组件需要启动,导致重复拉起(创建)应用进程 。继续看重载方法startProcessLocked:
//ActivityManagerService.javaprivate final void startProcessLocked(...){//应用进程的主线程的类名if (entryPoint == null) entryPoint = "android.app.ActivityThread";ProcessStartResult startResult = Process.start(entryPoint, ...);}//Process.javapublic static final ProcessStartResult start(...){return zygoteProcess.start(...);}
来到ZygoteProcess 。//ZygoteProcess.javapublic final Process.ProcessStartResult start(...){return startViaZygote(...);}private Process.ProcessStartResult startViaZygote(...){ArrayList<String> argsForZygote = new ArrayList<String>();//...处理各种参数return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);}
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 常用iOS应用的小组件推荐!超实用
- 6张图让你搞懂浏览器渲染网页过程
- Linux 上部署 Java 应用绕不开的命令,撒花啦
- 应用程序合成生成交换机代码
- 详解 gcc 编译、链接原理—揭开应用程序运行背后的奥秘
- Netflix如何实现Android与 iOS共用一套代码?
- 锌锰干电池原理和应用介绍
- 电池修复仪原理介绍及应用
- 恋爱行为学的实际应用解析
- 全方位理解哈希算法及其应用,不再迷茫