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启动过程源码分析

相关文章
|
23天前
|
Linux
百度搜索:蓝易云【Linux系统ps命令:查看正在运行的进程】
通过这些简洁的ps命令用法,你可以方便地查看Linux系统中正在运行的进程信息。
18 1
|
30天前
|
Linux
|
1月前
|
存储 算法 Linux
【Linux系统编程】进程状态
【Linux系统编程】进程状态
|
1月前
|
Linux Shell 调度
【Linux系统编程】进程的认识
【Linux系统编程】进程的认识
|
1月前
|
Linux 调度 Android开发
【系统启动】Kernel怎么跳转到Android:linux与安卓的交界
【系统启动】Kernel怎么跳转到Android:linux与安卓的交界
33 0
|
21小时前
|
安全 开发工具 Android开发
安卓与iOS系统的优缺点比较
【2月更文挑战第6天】 安卓和iOS是目前市场上最流行的两种操作系统。虽然它们都拥有自己的独特之处,但它们也有一些共同之处。本文将探讨这两种操作系统的优缺点,并对它们进行比较。
|
21小时前
|
Android开发 数据安全/隐私保护 iOS开发
安卓与iOS系统的发展趋势与比较分析
【2月更文挑战第6天】 在移动互联网时代,安卓和iOS系统作为两大主流移动操作系统,各自呈现出不同的发展趋势。本文将从技术角度出发,对安卓和iOS系统的发展方向、特点及未来趋势进行比较分析,以期为读者提供更深入的了解和思考。
|
1天前
|
小程序 JavaScript Java
android电子班牌人脸识别系统源码
智慧校园云平台全套源码包含:电子班牌管理系统、成绩管理系统、考勤人脸刷卡管理系统、综合素养评价系统、请假管理系统、电子班牌发布系统、校务管理系统、小程序移动端、教师后台管理系统、SaaS运营云平台。
11 1
|
3天前
|
搜索推荐 安全 Android开发
探索安卓与iOS系统的差异与共通之道
【2月更文挑战第4天】安卓与iOS作为当前主流的移动操作系统,各自拥有独特的特性和功能。本文将深入探讨安卓和iOS系统的差异,并提出一些共通之道,帮助读者更好地了解和应用这两个系统。
|
3天前
|
人工智能 vr&ar Android开发
探索安卓与iOS系统的技术进展
【2月更文挑战第4天】本文将探讨安卓与iOS两大操作系统在最新技术进展方面的差异与相似之处。我们将分析它们在人工智能、增强现实、隐私保护等方面的创新和发展,并展望未来可能出现的趋势。通过对比这两个操作系统的技术特点,读者将能够更好地了解并选择适合自己需求的智能设备。

相关产品

  • 云迁移中心
  • 相关实验场景

    更多