Android Framework(一)--对Zygote的理解

Zygote作为Android系统的核心组成部分,负责启动SystemServer和孵化应用进程。其通过fork+execve方式启动,先执行native函数启动虚拟机,再切换到Java层预加载资源。Zygote使用Socket而非Binder进行IPC通信,以避免多线程问题。其工作原理确保了系统服务的高效和稳定。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

zygote的作用

zygote的启动流程

问题:启动进程有几种方式?

问题:Zygote进程启动之后做了什么?

(一)先执行native函数 

(二)切换到java后

问题:Zygote fork为什么要单线程执行

Zygote的工作原理

问题:Zygote的IPC通信为什么不采用Binder?如果采用Binder的话会有什么问题?

问题:孵化应用进程为什么不交给SystemServer?而是专门设计一个Zygote?

zygote启动总结:


zygote的作用

  1. 启动SystemServer

        系统服务进程SystemServer是由Zygote进程fork出的(系统中比较重要的ActivityManagerService、PackageManagerService,WindowManagerService以及PowerManagerService等也是由SystemServer进程创建而来的),fork出的SystemServer进程会继承Zygote的资源,比如:常用类、JNI函数、主题资源、共享库等。

      2.孵化应用进程

        参考android的启动流程 , 里面有一个方法zygoteSendArgsAndGetResult方法,就是AMS请求Zygote来创建新的应用程序进程的。

补充 :

        启动三段式(独立进程都符合) : 进程启动->准备工作->LOOP(接收/处理)

zygote的启动流程

        init进程是Linux进程的第一个进程,它会加载启动配置文件init.rc。init.rc包含了众多的系统配置服务,里面就包含了要启动Zygote进程的配置

         采用fork+execve模式启动,pid为0是子进程;默认情况,创建子进程是继承了父进程的系统资源,但是调用了execve系统调用去加载另一个二进制程序的话,继承的父进程的系统资源就会被替换成加载的二进制程序

问题:启动进程有几种方式?

两种 : fork+handle / fork+execve    

流程:

  1. 调用fork()函数
  2. 判断pid是不是等于0来确定当前进程是父进程还是子进程

补充:

  1. 父子进程判断:fork()函数获取pid,父进程返回的是子进程的pid,
  2. 信号处理--SIGCHLD : 父进程fork出子进程,如果子进程挂了,父进程会收到sigchld信号, 比如zygote进程挂了,init进程收到信号会重启zygote进程

问题:Zygote进程启动之后做了什么?

(一)先执行native函数 

启动Android虚拟机->注册AndroidJNI函数->切换到java

     主要:在app_main.cpp中执行main()函数,内部执行JNI_CreateJavaVM()创建虚拟机

补充:

        创建虚拟机的位置在:
        AndroidRuntime.cpp中的startVm方法来启动虚拟机,startReg来注册JNI函数,CallStaticVoidMethod(startClass, startMeth, strArray)来调用ZygoteInit类的main方法,启动java部分。

注意:

        应用程序的虚拟机是继承Zygote进程的,然后再重置虚拟机的状态,再重启下虚拟机。

(二)切换到java后

  1.     Preload Resources:为fork子进程时提供相关的类,主题相关的资源,共享库
  2.     fork后,启动SystemServer
  3.     启动loop循环, 等待socket消息, 使用socket与SystemServer进行通信

        用于AMS通信,参考android启动流程中的ZygoteState.connect(mSocket),这里会创建Socket链接,在接受到AMS跨进程发过来的消息后,会调用handleChildProc启动ActivityThread.main()方法,进入新的进程了

问题:Zygote fork为什么要单线程执行

        Zygote里面有很多其他线程,为了保证状态一致,在fork子进程的时候,会停掉其他线程,在fork完成后,再恢复。可以理解为fork只能拷贝当前线程,不支持多线程的fork

Zygote的工作原理

问题:Zygote的IPC通信为什么不采用Binder?如果采用Binder的话会有什么问题?

        Zygote的IPC通信使用的是Socket

        Zygote的mian方法中会创建一个server端Socket(LocalSocket\LocalServerSocket),用于等待AMS请求Zygote来创建新的应用程序进程的,并且封装了TCP/IP协议,去掉网络相关。

原因:

  1. 为了避免父亲进程死锁、状态不一致等其他多线程问题,如果采用binder,在父进程binder线程有锁,然后子进程的主线程一直在等其子线程的资源,但是其实父进程的子进程并没有被拷贝过来,造成死锁,所以fork流程不允许存在多线程。而Binder通信是多线程的。
  2. 对于Zygote和SystemServer而言,Socket更加简单便捷,也符合单线程规范。

注意

        binder线程的初始化是在ServiceManger初始化的,而ServiceManger是Init进程孵化的,比Zygote进程更早,所以就不存在先后顺序问题。

问题:孵化应用进程为什么不交给SystemServer?而是专门设计一个Zygote?

        因为效率问题,SystemServer里面会跑一些其他的服务,如果SystemServer来fork进程,可能造成资源污染,不适合继承。而Zygote进程专门设计来干这事的。

zygote启动总结

  1. init进程fork出zygote进程
  2. 启动虚拟机, 注册JNI函数
  3. 预加载系统资源
  4. 启动SystemServer
  5. 启动Socket Loop, 等待socket消息
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值