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

相关文章
|
1月前
麒麟系统mate-indicators进程占用内存过高问题解决
【10月更文挑战第7天】麒麟系统mate-indicators进程占用内存过高问题解决
156 2
|
2月前
|
监控
MASM32写的免费软件“ProcView/系统进程监控” V1.4.4003 说明和下载
MASM32写的免费软件“ProcView/系统进程监控” V1.4.4003 说明和下载
|
1月前
麒麟系统mate-indicators进程占用内存过高问题解决
【10月更文挑战第5天】麒麟系统mate-indicators进程占用内存过高问题解决
125 0
|
2月前
|
监控 Ubuntu API
Python脚本监控Ubuntu系统进程内存的实现方式
通过这种方法,我们可以很容易地监控Ubuntu系统中进程的内存使用情况,对于性能分析和资源管理具有很大的帮助。这只是 `psutil`库功能的冰山一角,`psutil`还能够提供更多关于系统和进程的详细信息,强烈推荐进一步探索这个强大的库。
42 1
|
2月前
|
Java Android开发 数据安全/隐私保护
Android中多进程通信有几种方式?需要注意哪些问题?
本文介绍了Android中的多进程通信(IPC),探讨了IPC的重要性及其实现方式,如Intent、Binder、AIDL等,并通过一个使用Binder机制的示例详细说明了其实现过程。
302 4
|
2月前
|
安全 开发者 Python
揭秘Python IPC:进程间的秘密对话,让你的系统编程更上一层楼
【9月更文挑战第8天】在系统编程中,进程间通信(IPC)是实现多进程协作的关键技术。IPC机制如管道、队列、共享内存和套接字,使进程能在独立内存空间中共享信息,提升系统并发性和灵活性。Python提供了丰富的IPC工具,如`multiprocessing.Pipe()`和`multiprocessing.Queue()`,简化了进程间通信的实现。本文将从理论到实践,详细介绍各种IPC机制的特点和应用场景,帮助开发者构建高效、可靠的多进程应用。掌握Python IPC,让系统编程更加得心应手。
31 4
|
2月前
|
监控 API
【原创】用Delphi编写系统进程监控程序
【原创】用Delphi编写系统进程监控程序
|
3月前
|
API Android开发
Android P 性能优化:创建APP进程白名单,杀死白名单之外的进程
本文介绍了在Android P系统中通过创建应用进程白名单并杀死白名单之外的进程来优化性能的方法,包括设置权限、获取运行中的APP列表、配置白名单以及在应用启动时杀死非白名单进程的代码实现。
62 1
|
3月前
|
数据安全/隐私保护 异构计算 Windows
【Azure 环境】 介绍两种常规的方法来监视Window系统的CPU高时的进程信息: Performance Monitor 和 Powershell Get-Counter
【Azure 环境】 介绍两种常规的方法来监视Window系统的CPU高时的进程信息: Performance Monitor 和 Powershell Get-Counter
|
API Android开发
【Android 插件化】Hook 插件化框架 ( Hook Activity 启动流程 | Hook 点分析 )(一)
【Android 插件化】Hook 插件化框架 ( Hook Activity 启动流程 | Hook 点分析 )(一)
171 0
【Android 插件化】Hook 插件化框架 ( Hook Activity 启动流程 | Hook 点分析 )(一)