Android zygote分析

  zygote是有init进程根据init.rc配置文件创建的。本来是执行名为app_process的程序后替换为zygote。app_process对应的源程序为App_main.cpp文件。

1、App_main.cpp

[–>App_main.cpp]

int main(int argc, char* const argv[])
{
if (!className.isEmpty()) {
......
//不是zygote模式时做一些设置,为调用RuntimeInit时使用
}else {
......
//在zygote模式下做一些设置,主要是一些参数的设置已传给后面启动zygote使用
}
......
if (!niceName.isEmpty()) {
        ......
        //改写进程名字,即把app_process改为zygote
        set_process_name(niceName.string());
    }
}
if (zygote) {
//在zygote模式下调用ZygoteInit
       runtime.start("com.android.internal.os.ZygoteInit", args);
    } else if (className) {
   //在非zygote模式下调用RuntimeInit
       runtime.start("com.android.internal.os.RuntimeInit", args);
    } else {
       .....
    }

App_main主要功能是调用了AppRuntime.start()这个函数以启动zygote。

2、AndroidRuntime.cpp

在App_main.main中调用了runtime.start函数,AppRuntime继承了AndroidRuntime,但它却没有覆盖基类的start方法,所以runtime.start其实是调用的AndroidRuntime.start方法。
[–>AndroidRuntime.cpp]

void AndroidRuntime::start(const char* className, const Vector<String8>& options)
{
    .....
    //设置ANDROID_ROOT环境变量
    const char* rootDir = getenv("ANDROID_ROOT");
    if (rootDir == NULL) {
        rootDir = "/system";
        .....
        setenv("ANDROID_ROOT", rootDir, 1);
    }
    .....
    //创建虚拟机
    if (startVm(&mJavaVM, &env) != 0) {
        return;
    }
    .....
    //注册JNI
    if (startReg(env) < 0) {
    .....
    }
    .....
    //通过反射机制调用
    //com.android.internal.os.zygoteInit.java的main函数
   jmethodID startMeth = env->GetStaticMethodID(startClass, "main","([Ljava/lang/String;)V");
   .....
   env->CallStaticVoidMethod(startClass, startMeth, strArray); 
   .....
}

在AndroidRuntime::start中主要有三个步骤
1、创建虚拟机
[–>AndroidRuntime.cpp]

int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv)
{
......
//在AndroidRuntime::startVm主要是对虚拟机的一些设置,比如设置虚拟机的heapsize大小
......
//最后会调用JNI_CreateJavaVM创建虚拟机,pEnv返回当前额JNIEnv变量
 if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) {
       ......
    }
......    
}

2、注册JNI函数,通过 AndroidRuntime::startReg方法
3、通过反射机制调用ZygoteInit.main方法。

3、ZygoteInit.java

[–>ZygoteInit.java]

 public static void main(String argv[]) {
  .....
  //注册zygote用的socket
  registerZygoteSocket(socketName);
  .....
  //加载类和各种资源
  preload();
  .....
  //启动SystemServer进程
  startSystemServer(abiList, socketName);
  .....
  //监听zygote请求
  runSelectLoop(abiList);
  .....
 }

其重要内容有一下几点

  1. 注册zygote用的socket,zygote与其他进程通信并没有使用Binder而是socket。
  2. 加载类和资源。会在在很多系统启动所需的类,以及相应的一些启动所需的资源。
  3. 创建系统服务system_server,启动一些系统核心程序 。
  4. 监听zygote的socket请求,一旦有客户请求就会调用相应的函数进行处理。

4、SystemServer

SystemServer子进程的启动方式
[–>ZygoteInit.java]

private static boolean startSystemServer(String abiList, String socketName){
...... 
pid = Zygote.forkSystemServer(
                    parsedArgs.uid, parsedArgs.gid,
                    parsedArgs.gids,
                    parsedArgs.debugFlags,
                    null,
                    parsedArgs.permittedCapabilities,
                    parsedArgs.effectiveCapabilities);
......
if (pid == 0) {
          ......
          handleSystemServerProcess(parsedArgs);
          ......
        }
}

  在startSystemServer方法中通过forkSystemServer创建了SystemServer进程。SystemServer子进程会调用handleSystemServerProcess来处理自己的任务,在handleSystemServerProcess关键是会调用 RuntimeInit.zygoteInit();
  
RuntimeInit主要工作如下
[–>RuntimeInit.java]

 public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)throws ZygoteInit.MethodAndArgsCaller {
 ......
 //native层初始化
 nativeZygoteInit();
 ......
 applicationInit(targetSdkVersion, argv, classLoader);
 ......
 }
   private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)throws ZygoteInit.MethodAndArgsCaller {
 ......
 //调用com.android.server.SystemServer.main方法
 invokeStaticMain(args.startClass, args.startArgs, classLoader);
 ...... 
 }

所以启动的SystemServer子进程会调用nativeZygoteInit();进行native层的初始化,以及调用invokeStaticMain启动SystemServer中的main方法。分别主要任务如下

  1. nativeZygoteInit是一个native函数,主要用来与Binder机制建立连接,这样SystemServer就能够使用Binder了。
  2. invokeStaticMain中是通过抛出异常来启动SystemServer中的main方法的。Zygote的main方法会截获这个异常,并调用caller.run();来启动SystemServer.main。

Zygote分裂产生SystemServer,起始就是为了调用com.android.server.SystemServer里的main方法,代码如下
[–>SystemServer.java]

public static void main(String[] args) {
        new SystemServer().run();
    }
private void run() {
    .....
    //为线程
    Looper.prepareMainLooper();
    .....
    //加载android_servers库,以及初始化一些本地服务
    System.loadLibrary("android_servers");
    nativeInit();//在这里面可能还把本线程加入Binder通信中,具体有没有我没去看源码。
    .....
    //创建系统服务,就是启动framework中的各种服务如ActivityManager就是在这个时候启动的
    startBootstrapServices();
    startCoreServices();
    startOtherServices();
    .....
    Looper.loop();
}

综上,SystemServer个人感觉最重要的任务就是创建启动系统所需的一些系统服务。

5、Zygote分裂

  Zygote的主要任务就是进行分裂的,每当有新的应用启动的时候,就会进行自动分裂,这样即可以减少系统的开销,又可以加快应用启动的速度。
  前面以说道Zygote已经先分裂出了SystemServer,并调用runSelectLoop监听客服请求。那么客服端是怎么发送请求的呢?以ActivityManagerService发送请求为例,这个服务也是有SystemServer创建的。ActivityManagerService经过一些列的调用会最终调用到Process.zygoteSendArgsAndGetResult方法,代码如下
[–>Process.java]

 private static ProcessStartResult zygoteSendArgsAndGetResult(ZygoteState zygoteState, ArrayList<String> args)
 throws ZygoteStartFailedEx {
 .....
 //这里是连接上Zygote的socket接口,zygoteState是个内部类,里面包含了一个connect方法用于连接socket
 final BufferedWriter writer = zygoteState.writer;
 .....
 //对连接上的socket进行写操作,即向runSelectLoop发送请求。
 writer.write(arg);
 writer.newLine();
 ......
 }

接下来看看runSelectLoop是怎么响应请求的。
[–>ZygoteInit.java]

private static void runSelectLoop(String abiList){
    .....
    //获取Socket连接
    ZygoteConnection newPeer = acceptCommandPeer(abiList);
    .....
    //对每个连接调用runOnce处理函数
    done = peers.get(index).runOnce();
    .....
}

[–>ZygoteConnection.java]

 boolean runOnce(){
     ......
     //更具请求分裂出一个子进程
     pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
                        parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, 
                        parsedArgs.seInfo,parsedArgs.niceName, fdsToClose, 
                        parsedArgs.instructionSet,parsedArgs.appDataDir);
     .....
     if (pid == 0) {
     .....
     //子进程处理函数
     handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
     .....
     }
 }
private void handleChildProc(...){
 .....
 ZygoteInit.invokeStaticMain(cloader, className, mainArgs);
 .....
}

代码中的ZygoteInit.invokeStaticMain与RuntimeInit中的invokeStaticMain相似,ZygoteInit.main也会捕获相应异常并调用caller.run();来启动android.app.ActivityThread的main方法。


以上所写还有许多不足遗漏之处,希望以后有机会加以改进。
(不可全信,但不可不信)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值