android体系课-系统启动流程-之zygote进程启动过程源码分析

简介: 笔者刚开始学习Android的时候也和大部分同学一样,只会使用一些应用层面的知识,对于一些比较常见的开源框架如<mark>RxJava</mark>,<mark>OkHttp</mark>,<mark>Retrofit</mark>,以及后来谷歌推出的<mark>协程</mark>等,都只在使用层面,对于他们<mark>内部原理</mark>,基本没有去了解觉得够用就可以了,又比如Activity,Service等四大组件的使用原理,系统开机过程,Launcher启动过程等知之甚少,知其然而不知其所以然,结果就是出现某些问题,不知道从哪里找原因,只能依赖万能的百度,但是百度看多了,你会发现自己

前言

本文主要记录笔者对Android系统启动流程的一个的一个过程了解

笔者刚开始学习Android的时候也和大部分同学一样,只会使用一些应用层面的知识,对于一些比较常见的开源框架如RxJava,OkHttp,Retrofit,以及后来谷歌推出的协程等,都只在使用层面,对于他们内部原理,基本没有去了解觉得够用就可以了,又比如Activity,Service等四大组件的使用原理,系统开机过程,Launcher启动过程等知之甚少,知其然而不知其所以然,结果就是出现某些问题,不知道从哪里找原因,只能依赖万能的百度,但是百度看多了,你会发现自己还是什么都不会,过一段时间可能就忘记了

  • 为了能更加深刻的理解这些机制,笔者决定自己深入Framework层面去考察下这些代码的机制:

讲解时间线如下:

对于源码解析部分,可能大家会有部分疑惑,我们列出部分:

  • 1.zygoye是什么?有什么作用

    答:zygote英文翻译是“孵化”。

在了解zygote之前首先我们需要知道我们进程是如何创建的?

我们安卓设备内核使用的是linux内核,
开机先是启动一个init进程,在init进程中会创建一个zygote进程,
zygote进程会启动java虚拟机并注册java-native 的jni方法,通过jni调用到java层的ZygoteInit,在这个类里面会注册一个ServerSocket用于设备创建应用进程的需要。
当启动一个应用需要创建一个进程时,会调用到这个ServerSocket的创建进程流程,主要是通过fork的方式创建进程,这样子进程就拥有了父进程所有的资源,
fork会返回两次,当返回的pid=0时说明现在是处于子进程,继续处理子进程流程就可以了。如果是SystemServer进程,则会启动各类服务,包括AMS,WMS等系统服务。

按上面所讲,zygote就是作为创建子进程的一个孵化器。

  • 2.SystemServer是什么?有什么作用?它与zygote的关系是什么?

答:SystemServer是一个由zygotefork出来的子进程,该进程主要作用是创建创建binder线程池和启动android运行需要的诸多系统服务,比如:AMS,PMS,WMS等并启动系统Launcher

  • 3.ActivityManagerService是什么?什么时候初始化的?有什么作用?

答:ActivityManagerService,简称AMS,服务端对象,负责统一调度系统中四大组件的生命周期。ActivityManagerService进行初始化的时机很明确,就是在SystemServer进程开启的时候,就会初始化ActivityManagerService

**APP和AMS其实是通过binder进行通讯的。**

binder机制简述。
    binder其实是进程间通信的一种方式,在linux进程中有socket,管道,共享内存,消息队列等方式,
    而由于binder对性能消耗低和安全性方面的考虑,android大量的使用了binder通讯 ,可以说binder是android的基石。
binder模型简述:
    首先我们binder是通过CS架构进行设计的:Client和Service
    先搞懂三个概念:client,server和serverManger
    server通过binder通讯将自己注册到serverManager中,client通过binder获取serverManager中注册的server,
    其实是获取一个handle,通过这个handle就可以在bidner驱动中找找到server进程和需要处理的方法地址等信息。
    从而间接实现了进程间通讯,这个是binder的一个简要概述,详细的需要去了解binder驱动实现原理。
  • 4.Launcher是什么?什么时候启动的?

    答:Launcher也是一个应用app,是在SystemServer启动的时候,启动的一个应用
    
    

5.Instrumentation是什么?和ActivityThread是什么关系?

答:Instrumentation是一个沟通Activity和AMS以及ActivityThread和Activity中间桥梁工具类
例如:Activity.startActivity
        ->mInstrumentation.execStartActivity
        ->ActivityManagerService.startActivity->ActivityThread.thread.scheduleLaunchActivity
        ->ActivityThread.handleLaunchActivity
        ->mInstrumentation.callActivityOnCreate

针对以上问题:笔者会以源码的方式呈现

我们先来看下Android设备启动过程

  • init进程 0号进程

作用

1.创建和挂载启动所需的文件系统:tmpfs,devpts,proc,sysfs,selinuxfs等

2.初始化和启动属性服务

3.设置子进程(zygote进程)异常退出处理函数。

在UNIX/linux中,父进程调用fork函数创建子进程,在子进程在异常退出后,如果父进程不知道子进程已经退出,其会在系统进程表中保留进程信息(进程号,退出状态和运行时间等),
这个子进程就变成僵尸进程,系统进程表是一项有限资源,如果系统进程被僵尸进程耗尽就会无法创建新的进程

4.解析init.rc文件,并启动孵化zygote进程(Android初始化语言)

5.启动孵化zygote进程,这个是本篇文章的分析重点,从源码角度分析了Android zygote进程启动过程

app_main.cpp

    int main(){
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
            AndroidRuntime.cpp:start:
            //启动java虚拟机
            startVm(&mJavaVM, &env, zygote) != 0;
            //注册android启动需要的jni方法
            startReg(env) < 0;
            //startClass="com.android.internal.os.ZygoteInit" startMeth=main方法
            env->CallStaticVoidMethod(startClass, startMeth, strArray); 
            //即调用ZygoteInit的main方法
            ZygoteInit.java:main{    
                //创建一个Server端的socket,socketName=“zygote” 用于接收应用的请求创建应用进程fork方式
                zygoteServer.registerServerSocket(socketName);
                    ZygoteServer.java:registerServerSocket
                //预加载系统类和系统资源
                preload(bootTimingsTraceLog){
                    preloadClasses();
                    preloadResources();
                    preloadOpenGL();
                    preloadSharedLibraries();
                    preloadTextResources();
                    WebViewFactory.prepareWebViewInZygote();
                }
                //启动SystemServer进程
                startSystemServer(abiList, socketName, zygoteServer){
                    //fork system server进程
                    pid = Zygote.forkSystemServer(parsedArgs.uid, parsedArgs.gid...);
                    //pid=0,说明运行在子进程中:SystemServer进程中
                    if (pid == 0) {
                        //关闭SystemServer进程中的socket,因为是通过fork创建,子进程也会有socket服务,需要关闭子进程的socket通道
                        zygoteServer.closeServerSocket();
                        //处理SystemServer进程
                        handleSystemServerProcess(parsedArgs){
                            //创建PathClassLoader
                            cl = createPathClassLoader(...);
                            //注释2
                            ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl){
                                //RuntimeInit初始化操作
                                RuntimeInit.commonInit();
                                    RuntimeInit.java:commonInit
                                    //设置主线程未捕获异常时回调的Handler,可以在app中替换
                                    Thread.setDefaultUncaughtExceptionHandler(new KillApplicationHandler());
                                //对应AndroidRunTime:com_android_internal_os_ZygoteInit_nativeZygoteInit:
                                ZygoteInit.nativeZygoteInit(){
                                    //gCurRuntime = AppRuntime在app_main.cpp中初始化
                                    gCurRuntime->onZygoteInit(); 
                                        sp<ProcessState> proc = ProcessState::self();
                                        //启动线程池,内部会循环获取其他应用发过来的数据,根据binder机制
                                        proc->startThreadPool();
                                }
                                RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader){
                                
                                    invokeStaticMain(args.startClass, args.startArgs, classLoader){
                                        //前面传入的是"com.android.server.SystemServer",加载类SystemServer
                                        cl = Class.forName(className, true, classLoader); 
                                        //反射获取SystemServer的main方法
                                        m = cl.getMethod("main", new Class[] { String[].class });
                                        //可以再注释1出捕获,最终进入SystemServer的main方法
                                        throw new Zygote.MethodAndArgsCaller(m, argv);
                                    }
                                }
                            }
                        }            
                    }
                }
                //这个还是在app_main进程中等待AMS创建新的应用程序进程 注释3
                zygoteServer.runSelectLoop(abiList){
                    while (true) {
                        StructPollfd[] pollFds = new StructPollfd[fds.size()];
                        for (int i = 0; i < pollFds.length; ++i) {
                            pollFds[i] = new StructPollfd();
                            pollFds[i].fd = fds.get(i);
                            pollFds[i].events = (short) POLLIN;
                        }
                        try {
                            //poll函数使用pollfd类型的结构来监控一组文件句柄
                            //https://blog.csdn.net/sijinxiaotongxue/article/details/81988411
                            Os.poll(pollFds, -1);
                        } catch (ErrnoException ex) {
                            throw new RuntimeException("poll failed", ex);
                        }
                        for (int i = pollFds.length - 1; i >= 0; --i) {
                            if ((pollFds[i].revents & POLLIN) == 0) {
                                continue;
                            }
                            if (i == 0) {i=0为connect阶段
                                ZygoteConnection newPeer = acceptCommandPeer(abiList);
                                peers.add(newPeer);
                                fds.add(newPeer.getFileDesciptor());
                            } else {
                                //不为0则说明AMS向孵化进程发出一个创建进程的请求,调用fork方式创建进程
                                boolean done = peers.get(i).runOnce(this){
                                    acceptCommandPeer.runOnce(this){
                                        //读客户端发来的数据
                                        args = readArgumentList();
                                        调用fork创建新的进程        
                                        pid = Zygote.forkAndSpecialize(...) 
                                    }
                                }        
                                //创建成功,移除ZygoteConnection
                                if (done) {
                                    peers.remove(i);
                                    fds.remove(i);
                                }
                            }
                        }
                    }
                    //0为子进程
                    if (pid == 0) { 
                        //关闭子进程的socket连接,子进程不需要创建socket
                        zygoteServer.closeServerSocket();
                        //处理子进程
                        handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
                            //和注释2一样内部为初始化和创建子进程的线程池和启动子进程
                            ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion,parsedArgs.remainingArgs, null /* classLoader */);
                                
                    }
                }
                catch (Zygote.MethodAndArgsCaller caller) {
                    //子进程入口 注释1,zygote进程还是在注释3处等待
                    caller.run();
                } 
                
            }
    }

zygote进程总结:

  • 1.启动java虚拟机
  • 2.注册android启动需要的jni方法
  • 3.调用com.android.internal.os.ZygoteInit的main方法

    • 3.1:创建一个Server端的socket,socketName=“zygote” 用于接收应用的请求创建应用进程:使用的fork方式
    • 3.2:预加载系统类和系统资源,如果进程是使用fork方式创建的,则这个预加载的类和资源也可以被子进程所用
    • 3.2:使用fork方式创建SystemServer进程,最终会在3.3处接收到socket请求并创建SystemServer进程。并在异常后调用caller.run()运行SystemServer的main方法;
      SystemServer进程中:

      • 3.2.1:创建PathClassLoader
      • 3.2.2:设置主线程未捕获异常时回调的Handler,可以在app中替换
      • 3.2.3:启动binder线程池
      • 3.2.4:使用抛出异常加反射的方式,启动SystemServer的main方法
    • 3.3:在app_main进程中等待AMS创建新的应用程序进程

下一篇我们会讲解关于SystemServer启动过程源码分析

相关文章
|
6月前
|
安全 算法 小程序
【03】微信支付商户申请下户到配置完整流程-微信开放平台创建APP应用-填写上传基础资料-生成安卓证书-获取Apk签名-申请+配置完整流程-优雅草卓伊凡
【03】微信支付商户申请下户到配置完整流程-微信开放平台创建APP应用-填写上传基础资料-生成安卓证书-获取Apk签名-申请+配置完整流程-优雅草卓伊凡
390 28
【03】微信支付商户申请下户到配置完整流程-微信开放平台创建APP应用-填写上传基础资料-生成安卓证书-获取Apk签名-申请+配置完整流程-优雅草卓伊凡
|
5月前
|
NoSQL 应用服务中间件 PHP
布谷一对一直播源码android版环境配置流程及功能明细
部署需基于 CentOS 7.9 系统,硬盘不低于 40G,使用宝塔面板安装环境,包括 PHP 7.3(含 Redis、Fileinfo 扩展)、Nginx、MySQL 5.6、Redis 和最新 Composer。Swoole 扩展需按步骤配置。2021.08.05 后部署需将站点目录设为 public 并用 ThinkPHP 伪静态。开发环境建议 Windows 操作系统与最新 Android Studio,基础配置涉及 APP 名称修改、接口域名更换、包名调整及第三方登录分享(如 QQ、微信)的配置,同时需完成阿里云与腾讯云相关设置。
|
6月前
|
监控 Shell Linux
Android调试终极指南:ADB安装+多设备连接+ANR日志抓取全流程解析,覆盖环境变量配置/多设备调试/ANR日志分析全流程,附Win/Mac/Linux三平台解决方案
ADB(Android Debug Bridge)是安卓开发中的重要工具,用于连接电脑与安卓设备,实现文件传输、应用管理、日志抓取等功能。本文介绍了 ADB 的基本概念、安装配置及常用命令。包括:1) 基本命令如 `adb version` 和 `adb devices`;2) 权限操作如 `adb root` 和 `adb shell`;3) APK 操作如安装、卸载应用;4) 文件传输如 `adb push` 和 `adb pull`;5) 日志记录如 `adb logcat`;6) 系统信息获取如屏幕截图和录屏。通过这些功能,用户可高效调试和管理安卓设备。
|
7月前
|
前端开发 Java Shell
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
452 20
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
7月前
|
Dart 前端开发 Android开发
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
181 4
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
Java 调度 Android开发
android体系课-系统启动流程-之SystemServer启动过程源码分析
笔者刚开始学习Android的时候也和大部分同学一样,只会使用一些应用层面的知识,对于一些比较常见的开源框架如<mark>RxJava</mark>,<mark>OkHttp</mark>,<mark>Retrofit</mark>,以及后来谷歌推出的<mark>协程</mark>等,都只在使用层面,对于他们<mark>内部原理</mark>,基本没有去了解觉得够用就可以了,又比如Activity,Service等四大组件的使用原理,系统开机过程,Launcher启动过程等知之甚少,知其然而不知其所以然,结果就是出现某些问题,不知道从哪里找原因,只能依赖万能的百度,但是百度看多了,你会发现自己

热门文章

最新文章